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 impl Error {
8 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 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 #[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 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 impl Error {
92 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 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 #[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 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}