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