use std::marker::PhantomData;
pub trait AsyncOkFlow<InputOk> {
type OutputOk;
fn apply_ok_async<'a>(
&'a self,
input: InputOk,
) -> impl Future<Output = Self::OutputOk> + Send + 'a;
fn then_async_ok<Next>(self, next: Next) -> AsyncOkFlowChain<Self, Next, InputOk>
where
Self: Sized,
Next: AsyncOkFlow<Self::OutputOk>,
{
AsyncOkFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
pub struct AsyncOkFlowChain<Head, Next, InputOk>
where
Head: AsyncOkFlow<InputOk>,
Next: AsyncOkFlow<Head::OutputOk>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputOk>,
}
impl<Head, Next, InputOk> AsyncOkFlow<InputOk> for AsyncOkFlowChain<Head, Next, InputOk>
where
Head: AsyncOkFlow<InputOk> + Send + Sync,
Next: AsyncOkFlow<Head::OutputOk> + Send + Sync,
InputOk: Send + Sync,
{
type OutputOk = Next::OutputOk;
fn apply_ok_async<'a>(
&'a self,
input_ok: InputOk,
) -> impl Future<Output = Self::OutputOk> + Send + 'a {
async {
let intermediate = self.head.apply_ok_async(input_ok).await;
self.next.apply_ok_async(intermediate).await
}
}
}
impl<Head, Next, InputOk> Clone for AsyncOkFlowChain<Head, Next, InputOk>
where
Head: AsyncOkFlow<InputOk> + Clone,
Next: AsyncOkFlow<Head::OutputOk> + Clone,
{
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
next: self.next.clone(),
_phantom: PhantomData,
}
}
}
impl<Head, Next, InputOk> Copy for AsyncOkFlowChain<Head, Next, InputOk>
where
Head: AsyncOkFlow<InputOk> + Copy,
Next: AsyncOkFlow<Head::OutputOk> + Copy,
{
}