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(self, f: F) -> ItemActionStage, F, Fut, S, E> where F: Fn(S, ()) -> Fut + Send + Sync, Fut: Future> + Send { ItemActionStage { _s: Default::default(), _e: std::marker::PhantomData, prev: self, actionf: f, } } } pub struct ItemActionStage where P: ItemAction, F: Fn(S, P::Output) -> Fut + Send + Sync, Fut: Future> + Send, { _s: std::marker::PhantomData, _e: std::marker::PhantomData, prev: P, actionf: F, } #[async_trait::async_trait] impl ItemAction for ItemActionStage where P: ItemAction + ItemAction + Send + Sync, F: Fn(S, P::Output) -> Fut + Send + Sync, Fut: Future> + Send, 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 ItemActionStage where P: ItemAction + Send + Sync, F: Fn(S, P::Output) -> Fut + Send + Sync, Fut: Future> + Send, S: Send + Sync, P::Output: Send + Sync, E: Send + Sync, O: Send + Sync, P::Error: Send + Sync, { #[allow(clippy::type_complexity)] pub fn act(self, g: G) -> ItemActionStage, G, GFut, S, E> where S: Send + Sync, G: Fn(S, as ItemAction>::Output) -> GFut + Send + Sync, GFut: Future> + Send, O2: Send + Sync, { ItemActionStage { _s: Default::default(), _e: 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, ())) } }