use std::future::Future; #[async_trait::async_trait] pub trait ItemAction { type Input; type Output; type Start; type Error; async fn action(&self, s: Self::Start, i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error>; async fn commit(&self, v: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error>; } pub struct ItemStateAction { _t: std::marker::PhantomData, _s: std::marker::PhantomData, _e: std::marker::PhantomData, } impl Default for ItemStateAction { fn default() -> ItemStateAction { ItemStateAction { _t: std::marker::PhantomData, _s: std::marker::PhantomData, _e: std::marker::PhantomData, } } } impl ItemStateAction where T: Send + Sync, S: Send + Sync, E: Send + Sync, { pub fn act<'a, O, F, Fut>(self, f: F) -> ItemActionStage<'a, O, ItemStateAction, F, Fut, S, E> where F: Fn(S, ()) -> Fut + Send + Sync + 'a, Fut: Future> + Send + 'a { ItemActionStage { _s: Default::default(), _e: std::marker::PhantomData, _a: Default::default(), prev: self, actionf: f, } } } pub struct ItemActionStage<'a, O, P, F, Fut, S, E> where P: ItemAction, F: Fn(S, P::Output) -> Fut + Send + Sync + 'a, Fut: Future> + Send + 'a, { _s: std::marker::PhantomData, _e: std::marker::PhantomData, _a: std::marker::PhantomData<&'a ()>, prev: P, actionf: F, } #[async_trait::async_trait] impl<'a, O, P: ItemAction, F, Fut, S, E> ItemAction for ItemActionStage<'a, O, P, F, Fut, S, E> where P: ItemAction + ItemAction + Send + Sync, F: Fn(S, P::Output) -> Fut + Send + Sync + 'a, Fut: Future> + Send + 'a, S: Send + Sync, P::Output: Send + Sync, E: Send + Sync, O: Send + Sync, P::Error: Send + Sync, { type Input = P::Output; type Output = O; type Start = S; type Error = P::Error; async fn action(&self, s: Self::Start, i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error> { (self.actionf)(s, i).await } async fn commit(&self, i: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error> { let (i, prev) = self.prev.commit(i).await?; self.action(i, prev).await } } impl<'a, O, P: ItemAction, F, Fut, S, E> ItemActionStage<'a, O, P, F, Fut, S, E> where P: ItemAction + Send + Sync, F: Fn(S, P::Output) -> Fut + Send + Sync + 'a, Fut: Future> + Send + 'a, S: Send + Sync, P::Output: Send + Sync, E: Send + Sync, O: Send + Sync, P::Error: Send + Sync, { #[allow(clippy::type_complexity)] pub fn act<'b, O2, G, GFut>(self, g: G) -> ItemActionStage<'b, O2, ItemActionStage<'a, O, P, F, Fut, S, E>, G, GFut, S, E> where S: Send + Sync, G: Fn(S, as ItemAction>::Output) -> GFut + Send + Sync + 'b, GFut: Future> + Send + 'b, O2: Send + Sync, { ItemActionStage { _s: Default::default(), _e: Default::default(), _a: Default::default(), prev: self, actionf: g, } } } #[async_trait::async_trait] impl ItemAction for ItemStateAction where T: Send + Sync, S: Send + Sync, E: Send + Sync, { type Input = T; type Output = (); type Start = T; type Error = E; async fn action(&self, s: Self::Start, _i: Self::Input) -> Result<(Self::Start, Self::Output), Self::Error> { Ok((s, ())) } async fn commit(&self, i: Self::Start) -> Result<(Self::Start, Self::Output), Self::Error> { Ok((i, ())) } }