use crate::Pipe;
use fatal_error::FatalError;
use std::error::Error as StdError;
pub trait ErrExt<I, O, E, R> {
fn escalate(self) -> Escalate<Self>
where
Self: Sized,
{
Escalate(self)
}
fn deescalate(self) -> Deescalate<Self>
where
Self: Sized,
{
Deescalate(self)
}
}
impl<I, O, E, R, P> ErrExt<I, O, E, R> for P where P: Pipe<I, O, E, R> {}
pub struct Escalate<P>(P);
impl<I, O, E, R, P: Pipe<I, O, E, R>> Pipe<I, O, E, R> for Escalate<P> {
fn apply(&mut self, input: I) -> crate::Result<R, O, E> {
self.0.apply(input).map_err(|x| x.escalate())
}
}
pub struct Deescalate<P>(P);
impl<I, O, E, R, P: Pipe<I, O, E, R>> Pipe<I, O, E, R> for Deescalate<P> {
fn apply(&mut self, input: I) -> crate::Result<R, O, E> {
self.0.apply(input).map_err(|x| x.deescalate())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Incomplete {
Unknown,
Size(usize),
}
impl std::fmt::Display for Incomplete {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Incomplete::Unknown => write!(f, "more bytes needed"),
Incomplete::Size(x) => write!(f, "at least {x} more bytes are needed"),
}
}
}
impl StdError for Incomplete {}
pub fn error<I, O, E, R, F>(mut f: F) -> impl Pipe<I, O, E, R>
where
F: FnMut() -> FatalError<E>,
{
move |_| Err(f())
}