use std::marker::PhantomData;
pub trait AsyncErrFlow<InputErr> {
type OutputErr;
fn apply_err_async<'a>(
&'a self,
input: InputErr,
) -> impl Future<Output = Self::OutputErr> + Send + 'a;
fn then_async_err<Next>(self, next: Next) -> AsyncErrFlowChain<Self, Next, InputErr>
where
Self: Sized,
Next: AsyncErrFlow<Self::OutputErr>,
{
AsyncErrFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
pub struct AsyncErrFlowChain<Head, Next, InputErr>
where
Head: AsyncErrFlow<InputErr>,
Next: AsyncErrFlow<Head::OutputErr>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputErr>,
}
impl<Head, Next, InputErr> AsyncErrFlow<InputErr> for AsyncErrFlowChain<Head, Next, InputErr>
where
Head: AsyncErrFlow<InputErr> + Send + Sync,
Next: AsyncErrFlow<Head::OutputErr> + Send + Sync,
InputErr: Send + Sync,
{
type OutputErr = Next::OutputErr;
fn apply_err_async<'a>(
&'a self,
input_err: InputErr,
) -> impl Future<Output = Self::OutputErr> + Send + 'a {
async {
let intermediate = self.head.apply_err_async(input_err).await;
self.next.apply_err_async(intermediate).await
}
}
}
impl<Head, Next, InputErr> Clone for AsyncErrFlowChain<Head, Next, InputErr>
where
Head: AsyncErrFlow<InputErr> + Clone,
Next: AsyncErrFlow<Head::OutputErr> + Clone,
{
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
next: self.next.clone(),
_phantom: PhantomData,
}
}
}
impl<Head, Next, InputErr> Copy for AsyncErrFlowChain<Head, Next, InputErr>
where
Head: AsyncErrFlow<InputErr> + Copy,
Next: AsyncErrFlow<Head::OutputErr> + Copy,
{
}