1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
use crate::Pipe;
use fatal_error::FatalError;
use std::error::Error as StdError;
/// Changes error behaviour
pub trait ErrExt<I, O, E, R> {
/// Makes non fatal errors fatal
fn escalate(self) -> Escalate<Self>
where
Self: Sized,
{
Escalate(self)
}
/// makes fatal errors non fatal
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> {}
/// [ErrExt::escalate] implementation
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())
}
}
/// [ErrExt::deescalate] implementation
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())
}
}
/// Incomplete error
///
/// This error is returned when a pipe needs more input items
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Incomplete {
/// an unknown number of items is needed
Unknown,
/// a minimum of items is needed
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 {}
/// creates a pipe that always return an error
/// ```
/// # use pipe_chain::{error, tag, str::{TagStrError, digits}, OrExt, Pipe, Incomplete, EitherExt};
/// # use fatal_error::FatalError;
/// #[derive(Debug, PartialEq)]
/// enum Error {
/// Tag(TagStrError),
/// Incomplete(Incomplete),
/// Other
/// }
///
/// impl From<TagStrError> for Error { fn from(e: TagStrError) -> Error { Error::Tag(e)} }
///
/// impl From<Incomplete> for Error { fn from(e: Incomplete) -> Error { Error::Incomplete(e) } }
///
/// impl std::error::Error for Error {}
///
/// impl std::fmt::Display for Error {
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// write!(f, "{self:?}")
/// }
/// }
///
///
/// assert_eq!(tag::<Error, _, _>("a").or(error(|| FatalError::Fatal(Error::Other))).apply("b"), Err(FatalError::Fatal(Error::Other)));
/// ```
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())
}