1mod root_err;
2mod std_err;
3
4use std::{
5 any::TypeId,
6 error::Error,
7 fmt::{self, Debug, Display, Formatter},
8};
9
10use self::{root_err::RootErr, std_err::StdErr};
11use crate::{Backtrace, Error2, Location, kind::ErrorKind, private, transform::SourceToTarget};
12
13pub struct BoxedError2 {
14 source: Box<dyn Error2 + Send + Sync + 'static>,
15}
16
17impl BoxedError2 {
18 #[inline]
19 const fn source_ref(&self) -> &(dyn Error + Send + Sync + 'static) {
20 &*self.source
21 }
22
23 #[inline]
24 const fn source_mut(&mut self) -> &mut (dyn Error + Send + Sync + 'static) {
25 &mut *self.source
26 }
27
28 #[inline]
29 fn source(self) -> Box<dyn Error + Send + Sync + 'static> {
30 self.source
31 }
32
33 #[inline]
34 pub fn is_root(&self) -> bool {
35 self.source_ref().is::<RootErr>()
36 }
37
38 fn generic_is_root<T: Error + 'static>() -> bool {
39 TypeId::of::<RootErr>() == TypeId::of::<T>()
40 }
41
42 #[inline]
43 pub fn is<T: Error + 'static>(&self) -> bool {
44 debug_assert!(!Self::generic_is_root::<T>());
45 let source = self.source_ref();
46
47 source.is::<StdErr<T>>() || source.is::<T>()
48 }
49
50 #[inline]
51 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<ErrorKind<&T, &Backtrace>> {
52 debug_assert!(!Self::generic_is_root::<T>());
53 let source = self.source_ref();
54
55 if let Some(StdErr { source, backtrace }) = source.downcast_ref::<StdErr<T>>() {
56 Some(ErrorKind::Std { source, backtrace })
57 } else if let Some(source) = source.downcast_ref::<T>() {
58 Some(ErrorKind::Err2 { source })
59 } else {
60 None
61 }
62 }
63
64 #[inline]
65 pub fn downcast_mut<T: Error + 'static>(
66 &mut self,
67 ) -> Option<ErrorKind<&mut T, &mut Backtrace>> {
68 debug_assert!(!Self::generic_is_root::<T>());
69 let source = self.source_ref();
70
71 if source.is::<StdErr<T>>() {
72 let StdErr { source, backtrace } =
73 self.source_mut().downcast_mut::<StdErr<T>>().unwrap();
74 Some(ErrorKind::Std { source, backtrace })
75 } else if source.is::<T>() {
76 let source = self.source_mut().downcast_mut::<T>().unwrap();
77 Some(ErrorKind::Err2 { source })
78 } else {
79 None
80 }
81 }
82
83 #[inline]
84 pub fn downcast<T: Error + 'static>(self) -> Result<ErrorKind<T, Backtrace>, Self> {
85 debug_assert!(!Self::generic_is_root::<T>());
86 let source = self.source_ref();
87
88 if source.is::<StdErr<T>>() {
89 let StdErr { source, backtrace } = *self.source().downcast::<StdErr<T>>().unwrap();
90 Ok(ErrorKind::Std { source, backtrace })
91 } else if source.is::<T>() {
92 let source = *self.source().downcast::<T>().unwrap();
93 Ok(ErrorKind::Err2 { source })
94 } else {
95 Err(self)
96 }
97 }
98}
99
100impl Display for BoxedError2 {
101 #[inline]
102 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
103 Display::fmt(&self.source, f)
104 }
105}
106
107impl Debug for BoxedError2 {
108 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
109 if f.alternate() {
110 Debug::fmt(&self.source, f)
111 } else {
112 Display::fmt(&self.source, f)?;
113 write!(f, "\n\n")?;
114
115 let m = self.backtrace().error_message();
116 Display::fmt(&m, f)
117 }
118 }
119}
120
121impl Error for BoxedError2 {
122 #[inline]
123 fn source(&self) -> Option<&(dyn Error + 'static)> {
124 if self.is_root() {
125 None
126 } else {
127 Some(&*self.source)
128 }
129 }
130}
131
132impl Error2 for BoxedError2 {
133 #[inline]
134 fn backtrace(&self) -> &Backtrace {
135 self.source.backtrace()
136 }
137
138 #[inline]
139 fn backtrace_mut(&mut self) -> &mut Backtrace {
140 self.source.backtrace_mut()
141 }
142}
143
144impl BoxedError2 {
145 #[track_caller]
146 #[inline]
147 pub fn from_root<R>(root: R) -> BoxedError2
148 where
149 R: Display + Debug + Send + Sync + 'static,
150 {
151 Self::from_root_with_location(root, Location::caller())
152 }
153
154 pub fn from_root_with_location<R>(root: R, location: Location) -> BoxedError2
155 where
156 R: Display + Debug + Send + Sync + 'static,
157 {
158 let mut error = BoxedError2 {
159 source: Box::new(RootErr::new(root)),
160 };
161
162 crate::push_error(&mut error, location);
163
164 error
165 }
166
167 #[track_caller]
168 #[inline]
169 pub fn from_std<T>(source: T) -> BoxedError2
170 where
171 T: Error + Send + Sync + 'static,
172 {
173 Self::from_std_with_location(source, Location::caller())
174 }
175
176 pub fn from_std_with_location<T>(source: T, location: Location) -> BoxedError2
177 where
178 T: Error + Send + Sync + 'static,
179 {
180 if (&source as &(dyn Error + Send + Sync)).is::<BoxedError2>() {
181 let mut e =
182 <dyn Error + Send + Sync>::downcast::<BoxedError2>(Box::new(source)).unwrap();
183
184 e.backtrace_mut().push_location(location);
185 *e
186 } else {
187 let mut error = BoxedError2 {
188 source: Box::new(StdErr::new(source)),
189 };
190
191 crate::push_error(&mut error, location);
192
193 error
194 }
195 }
196
197 #[track_caller]
198 #[inline]
199 pub fn from_err2<T>(source: T) -> BoxedError2
200 where
201 T: Error2 + Send + Sync + 'static,
202 {
203 Self::from_err2_with_location(source, Location::caller())
204 }
205
206 pub fn from_err2_with_location<T>(source: T, location: Location) -> BoxedError2
207 where
208 T: Error2 + Send + Sync + 'static,
209 {
210 if (&source as &(dyn Error + Send + Sync)).is::<BoxedError2>() {
211 let mut e =
212 <dyn Error + Send + Sync>::downcast::<BoxedError2>(Box::new(source)).unwrap();
213
214 e.backtrace_mut().push_location(location);
215 *e
216 } else {
217 let mut error = BoxedError2 {
218 source: Box::new(source),
219 };
220
221 crate::push_error(&mut error, location);
222
223 error
224 }
225 }
226}
227
228pub struct ViaRoot<M>(pub M)
229where
230 M: Display + Debug + Send + Sync + 'static;
231
232impl<M> SourceToTarget<private::ViaFull, (), (), BoxedError2> for ViaRoot<M>
233where
234 M: Display + Debug + Send + Sync + 'static,
235{
236 #[inline]
237 fn source_to_target(self, _source: (), location: Location) -> BoxedError2 {
238 BoxedError2::from_root_with_location(self.0, location)
239 }
240}
241
242pub struct ViaStd;
243
244impl<T> SourceToTarget<private::ViaFull, T, T, BoxedError2> for ViaStd
245where
246 T: Error + Send + Sync + 'static,
247{
248 #[inline]
249 fn source_to_target(self, source: T, location: Location) -> BoxedError2 {
250 BoxedError2::from_std_with_location(source, location)
251 }
252}
253
254pub struct ViaErr2;
255
256impl<T> SourceToTarget<private::ViaFull, T, T, BoxedError2> for ViaErr2
257where
258 T: Error2 + Send + Sync + 'static,
259{
260 #[inline]
261 fn source_to_target(self, source: T, location: Location) -> BoxedError2 {
262 BoxedError2::from_err2_with_location(source, location)
263 }
264}