gix_error/
error.rs

1#[cfg(any(feature = "tree-error", not(feature = "auto-chain-error")))]
2mod _impl {
3    use crate::{Error, Exn};
4    use std::fmt::Formatter;
5
6    /// Utilities
7    impl Error {
8        /// Return the error that is most likely the root cause, based on heuristics.
9        /// Note that if there is nothing but this error, i.e. no source or children, this error is returned.
10        pub fn probable_cause(&self) -> &(dyn std::error::Error + 'static) {
11            let root = self.inner.frame();
12            root.probable_cause().unwrap_or(root).error()
13        }
14
15        /// Return an iterator over all errors in the tree in breadth-first order, starting with this one.
16        pub fn sources(&self) -> impl Iterator<Item = &(dyn std::error::Error + 'static)> + '_ {
17            self.inner.frame().iter_frames().map(|f| f.error() as _)
18        }
19    }
20
21    pub(crate) enum Inner {
22        ExnAsError(Box<crate::exn::Frame>),
23        Exn(Box<crate::exn::Frame>),
24    }
25
26    impl Inner {
27        fn frame(&self) -> &crate::exn::Frame {
28            match self {
29                Inner::ExnAsError(f) | Inner::Exn(f) => f,
30            }
31        }
32    }
33
34    impl Error {
35        /// Create a new instance representing the given `error`.
36        #[track_caller]
37        pub fn from_error(error: impl std::error::Error + Send + Sync + 'static) -> Self {
38            Error {
39                inner: Inner::ExnAsError(Exn::new(error).into()),
40            }
41        }
42    }
43
44    impl std::fmt::Display for Error {
45        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46            match &self.inner {
47                Inner::ExnAsError(err) => std::fmt::Display::fmt(err.error(), f),
48                Inner::Exn(frame) => std::fmt::Display::fmt(frame, f),
49            }
50        }
51    }
52
53    impl std::fmt::Debug for Error {
54        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55            match &self.inner {
56                Inner::ExnAsError(err) => std::fmt::Debug::fmt(err.error(), f),
57                Inner::Exn(frame) => std::fmt::Debug::fmt(frame, f),
58            }
59        }
60    }
61
62    impl std::error::Error for Error {
63        /// Return the first source of an [Exn] error, or the source of a boxed error.
64        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
65            match &self.inner {
66                Inner::ExnAsError(frame) | Inner::Exn(frame) => frame.children().first().map(|f| f.error() as _),
67            }
68        }
69    }
70
71    impl<E> From<Exn<E>> for Error
72    where
73        E: std::error::Error + Send + Sync + 'static,
74    {
75        fn from(err: Exn<E>) -> Self {
76            Error {
77                inner: Inner::Exn(err.into()),
78            }
79        }
80    }
81}
82#[cfg(any(feature = "tree-error", not(feature = "auto-chain-error")))]
83pub(super) use _impl::Inner;
84
85#[cfg(all(feature = "auto-chain-error", not(feature = "tree-error")))]
86mod _impl {
87    use crate::{Error, Exn};
88    use std::fmt::Formatter;
89
90    /// Utilities
91    impl Error {
92        /// Return the error that is most likely the root cause, based on heuristics.
93        /// Note that if there is nothing but this error, i.e. no source or children, this error is returned.
94        pub fn probable_cause(&self) -> &(dyn std::error::Error + 'static) {
95            use std::error::Error;
96            self.inner
97                .source()
98                .unwrap_or(self as &(dyn std::error::Error + 'static))
99        }
100
101        /// Return an iterator over all errors in the tree in breadth-first order, starting with this one.
102        pub fn sources(&self) -> impl Iterator<Item = &(dyn std::error::Error + 'static)> + '_ {
103            std::iter::successors(Some(&self.inner as &(dyn std::error::Error + 'static)), |err| {
104                err.source()
105            })
106        }
107    }
108
109    impl Error {
110        /// Create a new instance representing the given `error`.
111        #[track_caller]
112        pub fn from_error(error: impl std::error::Error + Send + Sync + 'static) -> Self {
113            Error {
114                inner: Exn::new(error).into_chain(),
115            }
116        }
117    }
118
119    impl std::fmt::Display for Error {
120        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
121            std::fmt::Display::fmt(&self.inner, f)
122        }
123    }
124
125    impl std::fmt::Debug for Error {
126        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
127            std::fmt::Debug::fmt(&self.inner, f)
128        }
129    }
130
131    impl std::error::Error for Error {
132        /// Return the first source of an [Exn] error, or the source of a boxed error.
133        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
134            self.inner.source()
135        }
136    }
137
138    impl<E> From<Exn<E>> for Error
139    where
140        E: std::error::Error + Send + Sync + 'static,
141    {
142        fn from(err: Exn<E>) -> Self {
143            Error {
144                inner: err.into_chain(),
145            }
146        }
147    }
148}