pretty-error-debug 0.3.2

If the process ends with an `Error`, write out the `Error` message and chain.
Documentation
extern crate alloc;

mod pretty_error_debug {
    pub(super) use crate::*;
}

use core::fmt;

use crate::{Display, Error, Wrapper};

#[derive(Debug, Clone, Copy)]
enum RootError {
    Reasons,
}

impl fmt::Display for RootError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            RootError::Reasons => write!(f, "Reasons"),
        }
    }
}

impl Error for RootError {}

#[derive(Debug, Clone, Copy)]
enum InnerError {
    Cause { root: RootError },
}

impl fmt::Display for InnerError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            InnerError::Cause { root } => write!(f, "Failed because of {:?}", root),
        }
    }
}

impl Error for InnerError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            InnerError::Cause { root } => Some(root),
        }
    }
}

impl From<RootError> for InnerError {
    fn from(root: RootError) -> Self {
        InnerError::Cause { root }
    }
}

#[derive(pretty_error_debug::Debug, Clone, Copy)]
enum OuterError {
    Inner(InnerError),
}

impl fmt::Display for OuterError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OuterError::Inner(_) => write!(f, "Got an InnerError"),
        }
    }
}

impl Error for OuterError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            OuterError::Inner(cause) => Some(cause),
        }
    }
}

impl From<InnerError> for OuterError {
    fn from(cause: InnerError) -> Self {
        OuterError::Inner(cause)
    }
}

#[derive(Debug, Clone, Copy)]
enum SimpleOuterError {
    Inner(InnerError),
}

impl fmt::Display for SimpleOuterError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            SimpleOuterError::Inner(_) => write!(f, "Got an InnerError"),
        }
    }
}

impl Error for SimpleOuterError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            SimpleOuterError::Inner(cause) => Some(cause),
        }
    }
}

impl From<InnerError> for SimpleOuterError {
    fn from(cause: InnerError) -> Self {
        SimpleOuterError::Inner(cause)
    }
}

fn root() -> Result<(), RootError> {
    Err(RootError::Reasons)
}

fn inner() -> Result<(), InnerError> {
    root().map_err(InnerError::from)
}

fn outer() -> Result<(), OuterError> {
    inner().map_err(OuterError::from)
}

fn simple_outer() -> Result<(), SimpleOuterError> {
    inner().map_err(SimpleOuterError::Inner)
}

const EXPECTED: &str = "\
Got an InnerError

Caused by:
    1: Failed because of Reasons
    2: Reasons\
";

#[test]
fn test_derive() {
    let outcome = alloc::format!("{:?}", outer().unwrap_err());
    assert_eq!(EXPECTED, &outcome);
}

#[test]
fn test_wrapper() {
    let outcome = alloc::format!("{:?}", Wrapper::from(simple_outer().unwrap_err()));
    assert_eq!(EXPECTED, &outcome);
}

#[test]
fn test_display() {
    let outcome = alloc::format!("{}", Display(&simple_outer().unwrap_err()));
    assert_eq!(EXPECTED, &outcome);
}