embedded-error-chain 1.0.0

Easy error handling in no-alloc and no-std environments
Documentation
use embedded_error_chain::{marker::Unused, *};
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
enum TestError1 {
    Err0 = 0,
    Err1 = 1,
}

impl ErrorCategory for TestError1 {
    const NAME: &'static str = "ErrorCategory";

    type L0 = Unused;
    type L1 = Unused;
    type L2 = Unused;
    type L3 = TestError3;
    type L4 = Unused;
    type L5 = Unused;
}

impl From<ErrorCode> for TestError1 {
    fn from(val: ErrorCode) -> Self {
        assert!(val <= TestError1::Err1 as u8);
        unsafe { core::mem::transmute(val) }
    }
}

impl Into<ErrorCode> for TestError1 {
    fn into(self) -> ErrorCode {
        self as ErrorCode
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
enum TestError2 {
    Err0 = 0,
    Err1 = 1,
}

impl ErrorCategory for TestError2 {
    const NAME: &'static str = "ErrorCategory";

    type L0 = TestError1;
    type L1 = Unused;
    type L2 = Unused;
    type L3 = Unused;
    type L4 = Unused;
    type L5 = Unused;
}

impl From<ErrorCode> for TestError2 {
    fn from(val: ErrorCode) -> Self {
        assert!(val <= TestError2::Err1 as u8);
        unsafe { core::mem::transmute(val) }
    }
}

impl Into<ErrorCode> for TestError2 {
    fn into(self) -> ErrorCode {
        self as ErrorCode
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
enum TestError3 {
    Err0 = 3,
    Err1 = 4,
}

impl ErrorCategory for TestError3 {
    const NAME: &'static str = "ErrorCategory";

    type L0 = TestError3;
    type L1 = TestError1;
    type L2 = TestError2;
    type L3 = Unused;
    type L4 = Unused;
    type L5 = Unused;
}

impl From<ErrorCode> for TestError3 {
    fn from(val: ErrorCode) -> Self {
        assert!(val <= TestError3::Err1 as u8);
        assert!(val >= TestError3::Err0 as u8);
        unsafe { core::mem::transmute(val) }
    }
}

impl Into<ErrorCode> for TestError3 {
    fn into(self) -> ErrorCode {
        self as ErrorCode
    }
}

#[test]
fn chain1() {
    let err = Error::new(TestError1::Err0);
    let err = err.chain(TestError2::Err1);

    assert_eq!(err.code(), TestError2::Err1);
    assert_eq!(
        err.code_of_category::<TestError1>().unwrap(),
        TestError1::Err0
    );
    assert_eq!(err.chain_len(), 1);

    let mut iter = err.iter();
    assert_eq!(
        iter.next(),
        Some((
            TestError2::Err1.into(),
            ErrorCategoryHandle::new::<TestError2>()
        ))
    );
    assert_eq!(
        iter.next(),
        Some((
            TestError1::Err0.into(),
            ErrorCategoryHandle::new::<TestError1>()
        ))
    );
    assert_eq!(iter.next(), None);
}

#[test]
fn chain2() {
    let err = Error::new(TestError2::Err1)
        .chain(TestError3::Err0)
        .chain(TestError3::Err1)
        .chain(TestError1::Err1)
        .chain(TestError2::Err0);

    let mut iter = err.iter();
    assert_eq!(
        iter.next(),
        Some((
            TestError2::Err0.into(),
            ErrorCategoryHandle::new::<TestError2>()
        ))
    );
    assert_eq!(
        iter.next(),
        Some((
            TestError1::Err1.into(),
            ErrorCategoryHandle::new::<TestError1>()
        ))
    );
    assert_eq!(
        iter.next(),
        Some((
            TestError3::Err1.into(),
            ErrorCategoryHandle::new::<TestError3>()
        ))
    );
    assert_eq!(
        iter.next(),
        Some((
            TestError3::Err0.into(),
            ErrorCategoryHandle::new::<TestError3>()
        ))
    );
    assert_eq!(
        iter.next(),
        Some((
            TestError2::Err1.into(),
            ErrorCategoryHandle::new::<TestError2>()
        ))
    );
    assert_eq!(iter.next(), None);
}

#[test]
#[should_panic(expected = "chaining two errors overflowed; error chain is full")]
fn chain3() {
    let _err = Error::new(TestError2::Err1)
        .chain(TestError3::Err0)
        .chain(TestError3::Err1)
        .chain(TestError1::Err1)
        .chain(TestError2::Err1)
        .chain(TestError3::Err0);
}