snapbox/assert/
error.rs

1pub type Result<T, E = Error> = std::result::Result<T, E>;
2
3#[derive(Clone, Debug)]
4pub struct Error {
5    inner: String,
6    backtrace: Option<Backtrace>,
7}
8
9impl Error {
10    pub fn new(inner: impl std::fmt::Display) -> Self {
11        Self::with_string(inner.to_string())
12    }
13
14    fn with_string(inner: String) -> Self {
15        Self {
16            inner,
17            backtrace: Backtrace::new(),
18        }
19    }
20
21    #[track_caller]
22    pub(crate) fn panic(self) -> ! {
23        panic!("{self}")
24    }
25}
26
27impl PartialEq for Error {
28    fn eq(&self, other: &Self) -> bool {
29        self.inner == other.inner
30    }
31}
32
33impl Eq for Error {}
34
35impl std::fmt::Display for Error {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        writeln!(f, "{}", self.inner)?;
38        if let Some(backtrace) = self.backtrace.as_ref() {
39            writeln!(f)?;
40            writeln!(f, "Backtrace:")?;
41            writeln!(f, "{backtrace}")?;
42        }
43        Ok(())
44    }
45}
46
47impl std::error::Error for Error {}
48
49impl<'s> From<&'s str> for Error {
50    fn from(other: &'s str) -> Self {
51        Self::with_string(other.to_owned())
52    }
53}
54
55impl<'s> From<&'s String> for Error {
56    fn from(other: &'s String) -> Self {
57        Self::with_string(other.clone())
58    }
59}
60
61impl From<String> for Error {
62    fn from(other: String) -> Self {
63        Self::with_string(other)
64    }
65}
66
67#[cfg(feature = "debug")]
68#[derive(Debug, Clone)]
69struct Backtrace(backtrace::Backtrace);
70
71#[cfg(feature = "debug")]
72impl Backtrace {
73    fn new() -> Option<Self> {
74        Some(Self(backtrace::Backtrace::new()))
75    }
76}
77
78#[cfg(feature = "debug")]
79impl std::fmt::Display for Backtrace {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        // `backtrace::Backtrace` uses `Debug` instead of `Display`
82        write!(f, "{:?}", self.0)
83    }
84}
85
86#[cfg(not(feature = "debug"))]
87#[derive(Debug, Copy, Clone)]
88struct Backtrace;
89
90#[cfg(not(feature = "debug"))]
91impl Backtrace {
92    fn new() -> Option<Self> {
93        None
94    }
95}
96
97#[cfg(not(feature = "debug"))]
98impl std::fmt::Display for Backtrace {
99    fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        Ok(())
101    }
102}