You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
3.9 KiB
140 lines
3.9 KiB
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<'a, O, F, Fut>(self, f: F) -> ItemActionStage<'a, O, ItemStateAction<T, S, E>, F, Fut, S, E>
|
|
where
|
|
F: Fn(S, ()) -> Fut + Send + Sync + 'a,
|
|
Fut: Future<Output=Result<(S, O), E>> + 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<Output=Result<(S, O) , E>> + Send + 'a,
|
|
{
|
|
_s: std::marker::PhantomData<S>,
|
|
_e: std::marker::PhantomData<E>,
|
|
_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<Start = S, Error = E> + Send + Sync,
|
|
F: Fn(S, P::Output) -> Fut + Send + Sync + 'a,
|
|
Fut: Future<Output=Result<(S, O), E>> + 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<Start = S, Error = E> + Send + Sync,
|
|
F: Fn(S, P::Output) -> Fut + Send + Sync + 'a,
|
|
Fut: Future<Output=Result<(S, O), E>> + 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, <ItemActionStage<'a, O, P, F, Fut, S, E> as ItemAction>::Output) -> GFut + Send + Sync + 'b,
|
|
GFut: Future<Output=Result<(S, O2), E>> + Send + 'b,
|
|
O2: Send + Sync,
|
|
{
|
|
ItemActionStage {
|
|
_s: Default::default(),
|
|
_e: Default::default(),
|
|
_a: 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, ()))
|
|
}
|
|
}
|