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 {
64 source: Box<dyn Error2 + Send + Sync + 'static>,
65}
66
67impl BoxedError2 {
68 #[inline]
69 const fn source_ref(&self) -> &(dyn Error + Send + Sync + 'static) {
70 &*self.source
71 }
72
73 #[inline]
74 const fn source_mut(&mut self) -> &mut (dyn Error + Send + Sync + 'static) {
75 &mut *self.source
76 }
77
78 #[inline]
79 fn source(self) -> Box<dyn Error + Send + Sync + 'static> {
80 self.source
81 }
82
83 #[inline]
85 pub fn is_root(&self) -> bool {
86 self.source_ref().is::<RootErr>()
87 }
88
89 fn generic_is_root<T: Error + 'static>() -> bool {
90 TypeId::of::<RootErr>() == TypeId::of::<T>()
91 }
92
93 #[inline]
95 pub fn is<T: Error + 'static>(&self) -> bool {
96 debug_assert!(!Self::generic_is_root::<T>());
97 let source = self.source_ref();
98
99 source.is::<StdErr<T>>() || source.is::<T>()
100 }
101
102 #[inline]
106 pub fn downcast_ref<T: Error + 'static>(&self) -> Option<ErrorKind<&T, &Backtrace>> {
107 debug_assert!(!Self::generic_is_root::<T>());
108 let source = self.source_ref();
109
110 if let Some(StdErr { source, backtrace }) = source.downcast_ref::<StdErr<T>>() {
111 Some(ErrorKind::Std { source, backtrace })
112 } else if let Some(source) = source.downcast_ref::<T>() {
113 Some(ErrorKind::Err2 { source })
114 } else {
115 None
116 }
117 }
118
119 #[inline]
121 pub fn downcast_mut<T: Error + 'static>(
122 &mut self,
123 ) -> Option<ErrorKind<&mut T, &mut Backtrace>> {
124 debug_assert!(!Self::generic_is_root::<T>());
125 let source = self.source_ref();
126
127 if source.is::<StdErr<T>>() {
128 let StdErr { source, backtrace } =
129 self.source_mut().downcast_mut::<StdErr<T>>().unwrap();
130 Some(ErrorKind::Std { source, backtrace })
131 } else if source.is::<T>() {
132 let source = self.source_mut().downcast_mut::<T>().unwrap();
133 Some(ErrorKind::Err2 { source })
134 } else {
135 None
136 }
137 }
138
139 #[inline]
143 pub fn downcast<T: Error + 'static>(self) -> Result<ErrorKind<T, Backtrace>, Self> {
144 debug_assert!(!Self::generic_is_root::<T>());
145 let source = self.source_ref();
146
147 if source.is::<StdErr<T>>() {
148 let StdErr { source, backtrace } = *self.source().downcast::<StdErr<T>>().unwrap();
149 Ok(ErrorKind::Std { source, backtrace })
150 } else if source.is::<T>() {
151 let source = *self.source().downcast::<T>().unwrap();
152 Ok(ErrorKind::Err2 { source })
153 } else {
154 Err(self)
155 }
156 }
157}
158
159impl Display for BoxedError2 {
160 #[inline]
161 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
162 Display::fmt(&self.source, f)
163 }
164}
165
166impl Debug for BoxedError2 {
167 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
168 if f.alternate() {
169 Debug::fmt(&self.source, f)
170 } else {
171 Display::fmt(&self.source, f)?;
172 write!(f, "\n\n")?;
173
174 let m = self.backtrace().error_message();
175 Display::fmt(&m, f)
176 }
177 }
178}
179
180impl Error for BoxedError2 {
181 #[inline]
182 fn source(&self) -> Option<&(dyn Error + 'static)> {
183 if self.is_root() {
184 None
185 } else {
186 Some(&*self.source)
187 }
188 }
189}
190
191impl Error2 for BoxedError2 {
192 #[inline]
193 fn backtrace(&self) -> &Backtrace {
194 self.source.backtrace()
195 }
196
197 #[inline]
198 fn backtrace_mut(&mut self) -> &mut Backtrace {
199 self.source.backtrace_mut()
200 }
201}
202
203impl BoxedError2 {
204 #[track_caller]
208 #[inline]
209 pub fn from_root<R>(root: R) -> BoxedError2
210 where
211 R: Display + Debug + Send + Sync + 'static,
212 {
213 Self::from_root_with_location(root, Location::caller())
214 }
215
216 pub fn from_root_with_location<R>(root: R, location: Location) -> BoxedError2
218 where
219 R: Display + Debug + Send + Sync + 'static,
220 {
221 let mut error = BoxedError2 {
222 source: Box::new(RootErr::new(root)),
223 };
224
225 crate::push_error(&mut error, location);
226
227 error
228 }
229
230 #[track_caller]
234 #[inline]
235 pub fn from_std<T>(source: T) -> BoxedError2
236 where
237 T: Error + Send + Sync + 'static,
238 {
239 Self::from_std_with_location(source, Location::caller())
240 }
241
242 pub fn from_std_with_location<T>(source: T, location: Location) -> BoxedError2
244 where
245 T: Error + Send + Sync + 'static,
246 {
247 if (&source as &(dyn Error + Send + Sync)).is::<BoxedError2>() {
248 let mut e =
249 <dyn Error + Send + Sync>::downcast::<BoxedError2>(Box::new(source)).unwrap();
250
251 e.backtrace_mut().push_location(location);
252 *e
253 } else {
254 let mut error = BoxedError2 {
255 source: Box::new(StdErr::new(source)),
256 };
257
258 crate::push_error(&mut error, location);
259
260 error
261 }
262 }
263
264 #[track_caller]
268 #[inline]
269 pub fn from_err2<T>(source: T) -> BoxedError2
270 where
271 T: Error2 + Send + Sync + 'static,
272 {
273 Self::from_err2_with_location(source, Location::caller())
274 }
275
276 pub fn from_err2_with_location<T>(source: T, location: Location) -> BoxedError2
278 where
279 T: Error2 + Send + Sync + 'static,
280 {
281 if (&source as &(dyn Error + Send + Sync)).is::<BoxedError2>() {
282 let mut e =
283 <dyn Error + Send + Sync>::downcast::<BoxedError2>(Box::new(source)).unwrap();
284
285 e.backtrace_mut().push_location(location);
286 *e
287 } else {
288 let mut error = BoxedError2 {
289 source: Box::new(source),
290 };
291
292 crate::push_error(&mut error, location);
293
294 error
295 }
296 }
297}
298
299pub struct ViaRoot<M>(pub M)
324where
325 M: Display + Debug + Send + Sync + 'static;
326
327impl<M> SourceToTarget<private::ViaFull, (), (), BoxedError2> for ViaRoot<M>
328where
329 M: Display + Debug + Send + Sync + 'static,
330{
331 #[inline]
332 fn source_to_target(self, _source: (), location: Location) -> BoxedError2 {
333 BoxedError2::from_root_with_location(self.0, location)
334 }
335}
336
337pub struct ViaStd;
353
354impl<T> SourceToTarget<private::ViaFull, T, T, BoxedError2> for ViaStd
355where
356 T: Error + Send + Sync + 'static,
357{
358 #[inline]
359 fn source_to_target(self, source: T, location: Location) -> BoxedError2 {
360 BoxedError2::from_std_with_location(source, location)
361 }
362}
363
364pub struct ViaErr2;
384
385impl<T> SourceToTarget<private::ViaFull, T, T, BoxedError2> for ViaErr2
386where
387 T: Error2 + Send + Sync + 'static,
388{
389 #[inline]
390 fn source_to_target(self, source: T, location: Location) -> BoxedError2 {
391 BoxedError2::from_err2_with_location(source, location)
392 }
393}