use std::fmt::Debug; type OpResult = Result< (::Output, ::Inverse), <::Target as OperatorTarget>::Error, >; type BindFn = fn( &::Target, Pass, ) -> Result::Target as OperatorTarget>::Error>; pub trait OperatorTarget { type Event; type Error; } pub trait Operator { type Input; type Output; type Target: OperatorTarget; type Inverse: Operator; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, input: Self::Input, ) -> OpResult where Self: Sized; fn seq(self, next: Op) -> Chain where Self: Sized, Op: Operator, { Chain(self, next) } fn bind(self, f: BindFn) -> Chain> where Self: Sized, Op: Operator, { Chain(self, Bind::new(f)) } fn with(self, input: Self::Input) -> Chain, Self> where Self: Sized, { Chain(Const::new(input), self) } } #[derive(Debug, Clone)] pub struct Chain(A, B); impl Operator for Chain where A: Operator, B: Operator, T: OperatorTarget, { type Input = S1; type Output = S3; type Target = T; type Inverse = Chain; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { let (s2, inv_a) = self.0.apply(target, events, input)?; let (s3, inv_b) = self.1.apply(target, events, s2)?; Ok((s3, Chain(inv_b, inv_a))) } } #[derive(Clone, Copy)] pub struct Read { f: fn(&Target, Input) -> Result, } impl Read { pub fn new(f: fn(&Target, Input) -> Result) -> Self { Self { f } } } impl Debug for Read { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Read").finish() } } impl Operator for Read where Input: Clone, { type Input = Input; type Output = Output; type Target = Target; type Inverse = Forget; fn apply( &self, target: &mut Self::Target, _events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok(((self.f)(target, input.clone())?, Forget::new(self.f, input))) } } #[derive(Clone, Copy)] pub struct Forget { f: fn(&Target, Input) -> Result, i: Input, } impl Forget { pub fn new(f: fn(&Target, Input) -> Result, i: Input) -> Self { Self { f, i } } } impl Debug for Forget { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Forget").finish() } } impl Operator for Forget where Input: Clone, { type Input = Output; type Output = Input; type Target = Target; type Inverse = Read; fn apply( &self, _target: &mut Self::Target, _events: &mut Vec<::Event>, _input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok((self.i.clone(), Read::new(self.f))) } } #[derive(Clone)] pub struct Bind { f: BindFn, } impl Bind { pub fn new(f: BindFn) -> Self { Self { f } } } impl Debug for Bind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Bind").finish() } } impl Operator for Bind where Op: Operator, Pass: Clone, { type Input = Pass; type Output = Op::Output; type Target = Op::Target; type Inverse = Bound; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { let op = (self.f)(target, input.clone())?; op.apply(target, events, ()) .map(|(out, inv)| (out, Bound::new(self.f, input, inv))) } } pub struct Bound { f: BindFn, i: Pass, inverse: ::Inverse, } impl Bound { pub fn new(f: BindFn, i: Pass, inverse: ::Inverse) -> Self { Self { f, i, inverse } } } impl Debug for Bound { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Bound").finish() } } impl Operator for Bound where Op: Operator, Pass: Clone, { type Input = Op::Output; type Output = Pass; type Target = Op::Target; type Inverse = Bind; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { let _ = self.inverse.apply(target, events, input)?; Ok((self.i.clone(), Bind::new(self.f))) } } #[derive(Clone)] pub struct Const(T, std::marker::PhantomData); impl Const { pub fn new(value: T) -> Self { Self(value, std::marker::PhantomData) } } impl From for Const { fn from(value: T) -> Self { Self::new(value) } } impl Debug for Const { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Const").finish() } } impl Operator for Const where T: Clone, Target: OperatorTarget, { type Input = (); type Output = T; type Target = Target; type Inverse = Discard; fn apply( &self, _target: &mut Self::Target, _events: &mut Vec<::Event>, _input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok((self.0.clone(), Discard::new())) } } #[derive(Clone)] pub struct Discard(std::marker::PhantomData<(T, Target)>); impl Discard { pub fn new() -> Self { Self(std::marker::PhantomData) } } impl Default for Discard { fn default() -> Self { Self::new() } } impl Debug for Discard { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Discard").finish() } } impl Operator for Discard where T: Clone, Target: OperatorTarget, { type Input = T; type Output = (); type Target = Target; type Inverse = Const; fn apply( &self, _target: &mut Self::Target, _events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok(((), Const::new(input))) } } #[derive(Clone)] pub struct Push(T, std::marker::PhantomData<(Input, Target)>); impl Push { pub fn new(value: T) -> Self { Self(value, std::marker::PhantomData) } } impl Debug for Push { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Push").finish() } } impl Operator for Push where T: Clone, Target: OperatorTarget, { type Input = Input; type Output = (Input, T); type Target = Target; type Inverse = Pop; fn apply( &self, _target: &mut Self::Target, _events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok(((input, self.0.clone()), Pop::new(self.0.clone()))) } } #[derive(Clone)] pub struct Pop(T, std::marker::PhantomData<(Input, Target)>); impl Pop { pub fn new(value: T) -> Self { Self(value, std::marker::PhantomData) } } impl Debug for Pop { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Pop").finish() } } impl Operator for Pop where T: Clone, Target: OperatorTarget, { type Input = (Input, T); type Output = Input; type Target = Target; type Inverse = Push; fn apply( &self, _target: &mut Self::Target, _events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { Ok((input.0, Push::new(self.0.clone()))) } } #[derive(Debug, Clone)] pub enum Or { Left(A, std::marker::PhantomData), Right(B, std::marker::PhantomData), } impl Operator for Or where A: Operator, B: Operator, T: OperatorTarget, { type Input = A::Input; type Output = A::Output; type Target = T; type Inverse = Or; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { match self { Or::Left(op, _) => op .apply(target, events, input) .map(|(out, inv)| (out, Or::Left(inv, std::marker::PhantomData))), Or::Right(op, _) => op .apply(target, events, input) .map(|(out, inv)| (out, Or::Right(inv, std::marker::PhantomData))), } } } pub trait ErasedOperator { type Target: OperatorTarget; fn apply_erased( &self, target: &mut Self::Target, events: &mut Vec<::Event>, ) -> Result< Box>, ::Error, >; } impl ErasedOperator for Box> { type Target = T; fn apply_erased( &self, target: &mut Self::Target, events: &mut Vec<::Event>, ) -> Result< Box>, ::Error, > { self.as_ref().apply_erased(target, events) } } impl ErasedOperator for Op where Op: Operator + 'static, Op::Output: Debug + Clone + 'static, Target: OperatorTarget, { type Target = Target; fn apply_erased( &self, target: &mut Self::Target, events: &mut Vec<::Event>, ) -> Result< Box>, ::Error, > { self.apply(target, events, ()).map(Into::into) } } impl ErasedOperator for (I, Op) where I: Debug + Clone + 'static, Ta: OperatorTarget, Op: Operator + 'static, Op::Output: Debug + Clone, { type Target = Ta; fn apply_erased( &self, target: &mut Self::Target, events: &mut Vec<::Event>, ) -> Result< Box>, ::Error, > { self.1.apply(target, events, self.0.clone()).map(Into::into) } } impl From for Box> where Op: Operator + 'static, Op::Output: Debug + Clone + 'static, Target: OperatorTarget, { fn from(op: Op) -> Self { Box::new(((), op)) } } impl From<(I, Op)> for Box> where I: Debug + Clone + 'static, Op: Operator + 'static, Op::Output: Debug + Clone + 'static, { fn from(op: (I, Op)) -> Self { Box::new(op) } } pub type ErasedOperators = Vec>>; impl Operator for ErasedOperators where Target: OperatorTarget, { type Input = (); type Output = (); type Target = Target; type Inverse = Self; fn apply( &self, target: &mut Self::Target, events: &mut Vec<::Event>, _input: Self::Input, ) -> Result<(Self::Output, Self::Inverse), ::Error> { let mut inverses = Vec::new(); for op in self { match op.apply_erased(target, events) { Ok(inv) => inverses.push(inv), Err(e) => { // Rollback all applied operators in reverse order for inv in inverses.into_iter().rev() { // Ignore errors during rollback to ensure best effort at restoring state let _ = inv.apply_erased(target, events); } return Err(e); } } } inverses.reverse(); Ok(((), inverses)) } }