use std::marker::PhantomData;
pub trait ErrFlow<InputErr> {
type OutputErr;
fn apply_err(&self, input: InputErr) -> Self::OutputErr;
fn then_err<Next>(self, next: Next) -> ErrFlowChain<Self, Next, InputErr>
where
Self: Sized,
Next: ErrFlow<Self::OutputErr>,
{
ErrFlowChain {
head: self,
next,
_phantom: PhantomData,
}
}
}
pub struct ErrFlowChain<Head, Next, InputErr>
where
Head: ErrFlow<InputErr>,
Next: ErrFlow<Head::OutputErr>,
{
head: Head,
next: Next,
_phantom: PhantomData<InputErr>,
}
impl<Head, Next, InputErr> ErrFlow<InputErr>
for ErrFlowChain<Head, Next, InputErr>
where
Head: ErrFlow<InputErr>,
Next: ErrFlow<Head::OutputErr>,
{
type OutputErr = Next::OutputErr;
fn apply_err(&self, input_err: InputErr) -> Self::OutputErr {
let result = self.head.apply_err(input_err);
self.next.apply_err(result)
}
}
impl<Head, Next, InputErr> Clone for ErrFlowChain<Head, Next, InputErr>
where
Head: ErrFlow<InputErr> + Clone,
Next: ErrFlow<Head::OutputErr> + Clone,
{
fn clone(&self) -> Self {
Self {
head: self.head.clone(),
next: self.next.clone(),
_phantom: PhantomData,
}
}
}
impl<FirstFlow, NextFlow, InputErr> Copy for ErrFlowChain<FirstFlow, NextFlow, InputErr>
where
FirstFlow: ErrFlow<InputErr> + Copy,
NextFlow: ErrFlow<FirstFlow::OutputErr> + Copy,
{
}