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<InputErr, Self, Next>
where
Self: Sized,
Next: AsyncErrFlow<Self::OutputErr>,
{
AsyncErrFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct AsyncErrFlowChain<InputErr, Head, Next>
where
Head: AsyncErrFlow<InputErr>,
Next: AsyncErrFlow<Head::OutputErr>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputErr>,
}
impl<InputErr, Head, Next> AsyncErrFlowChain<InputErr, Head, Next>
where
Head: AsyncErrFlow<InputErr>,
Next: AsyncErrFlow<Head::OutputErr>,
{
pub fn new(head: Head, next: Next) -> Self {
Self {
head,
next,
_phantom: PhantomData,
}
}
pub const fn new_const(head: Head, next: Next) -> Self {
Self {
head,
next,
_phantom: PhantomData,
}
}
}
impl<InputErr, Head, Next> AsyncErrFlow<InputErr> for AsyncErrFlowChain<InputErr, Head, Next>
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
}
}
}