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

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, ()))
}
}