erdp/
lib.rs

1//! Small crate with zero dependencies to help you display an error.
2#![no_std]
3
4pub use self::wrapper::*;
5
6use core::error::Error;
7use core::fmt::Formatter;
8
9extern crate alloc;
10
11mod wrapper;
12
13/// Provides a method to get a [Display].
14///
15/// This trait is automatically implemented for any type that implement [core::error::Error].
16pub trait ErrorDisplay {
17    /// Returns a [Display] to display current error and its nested errors.
18    fn display(&self) -> Display<'_>;
19}
20
21impl<T: Error> ErrorDisplay for T {
22    #[inline(always)]
23    fn display(&self) -> Display<'_> {
24        Display(self)
25    }
26}
27
28impl ErrorDisplay for dyn Error {
29    #[inline(always)]
30    fn display(&self) -> Display<'_> {
31        Display(self)
32    }
33}
34
35/// Implementation of [core::fmt::Display] to display an error and its nested errors.
36pub struct Display<'a>(&'a dyn Error);
37
38impl<'a> core::fmt::Display for Display<'a> {
39    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
40        // Write top-level error.
41        core::fmt::Display::fmt(self.0, f)?;
42
43        // Write nested errors.
44        let mut next = self.0.source();
45
46        while let Some(e) = next {
47            f.write_str(" -> ")?;
48            core::fmt::Display::fmt(e, f)?;
49            next = e.source();
50        }
51
52        Ok(())
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use std::prelude::rust_2024::*;
60    use thiserror::Error;
61
62    extern crate std;
63
64    #[test]
65    fn single() {
66        let e = TestError::Single;
67
68        assert_eq!(e.display().to_string(), "an error without nested errors");
69    }
70
71    #[test]
72    fn nested() {
73        let e = std::io::Error::from(std::io::ErrorKind::NotFound);
74        let e = TestError::Nested(e);
75
76        assert_eq!(e.display().to_string(), "nested error -> entity not found");
77    }
78
79    #[test]
80    fn trait_object() {
81        let e: Box<dyn Error> = Box::new(TestError::Single);
82
83        assert_eq!(e.display().to_string(), "an error without nested errors");
84    }
85
86    #[derive(Debug, Error)]
87    enum TestError {
88        #[error("an error without nested errors")]
89        Single,
90
91        #[error("nested error")]
92        Nested(#[source] std::io::Error),
93    }
94}