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