use std::marker::PhantomData;
pub trait AsyncResultFlow<InputOk, InputErr> {
type OutputOk;
type OutputErr;
fn apply_result_async<'a>(
&'a self,
input: Result<InputOk, InputErr>,
) -> impl Future<Output = Result<Self::OutputOk, Self::OutputErr>> + Send + 'a;
fn then_async_result<Next>(
self,
next: Next,
) -> AsyncResultFlowChain<Self, Next, InputOk, InputErr>
where
Self: Sized,
Next: AsyncResultFlow<Self::OutputOk, Self::OutputErr>,
{
AsyncResultFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
pub struct AsyncResultFlowChain<Head, Next, InputOk, InputErr>
where
Head: AsyncResultFlow<InputOk, InputErr>,
Next: AsyncResultFlow<Head::OutputOk, Head::OutputErr>,
{
head: Head,
next: Next,
_phantom: PhantomData<(InputOk, InputErr)>,
}
impl<Head, Next, InputOk, InputErr> AsyncResultFlow<InputOk, InputErr>
for AsyncResultFlowChain<Head, Next, InputOk, InputErr>
where
Head: AsyncResultFlow<InputOk, InputErr> + Send + Sync,
Next: AsyncResultFlow<Head::OutputOk, Head::OutputErr> + Send + Sync,
InputOk: Send + Sync,
InputErr: Send + Sync,
{
type OutputOk = Next::OutputOk;
type OutputErr = Next::OutputErr;
fn apply_result_async<'a>(
&'a self,
input_result: Result<InputOk, InputErr>,
) -> impl Future<Output = Result<Self::OutputOk, Self::OutputErr>> + Send + 'a {
async {
let intermediate = self.head.apply_result_async(input_result).await;
self.next.apply_result_async(intermediate).await
}
}
}
impl<Head, Next, InputOk, InputErr> Clone for AsyncResultFlowChain<Head, Next, InputOk, InputErr>
where
Head: AsyncResultFlow<InputOk, InputErr> + Clone,
Next: AsyncResultFlow<Head::OutputOk, Head::OutputErr> + Clone,
{
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
next: self.next.clone(),
_phantom: PhantomData,
}
}
}
impl<Head, Next, InputOk, InputErr> Copy for AsyncResultFlowChain<Head, Next, InputOk, InputErr>
where
Head: AsyncResultFlow<InputOk, InputErr> + Copy,
Next: AsyncResultFlow<Head::OutputOk, Head::OutputErr> + Copy,
{
}