1use core::{error, fmt};
2
3use crate::{thin_box::ThinBox, Source, Trace};
4
5#[ptr_meta::pointee]
6trait ErrorTrace: fmt::Debug + fmt::Display + Send + Sync + 'static {}
7
8impl<T> ErrorTrace for T where
9 T: fmt::Debug + fmt::Display + Send + Sync + 'static + ?Sized
10{
11}
12
13#[derive(Debug)]
14struct ErrorWithTrace {
15 error: BoxedError,
16 trace: ThinBox<dyn ErrorTrace>,
17}
18
19impl fmt::Display for ErrorWithTrace {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 write!(f, "{}", self.error)?;
22 write!(f, "trace: {}", self.trace)?;
23
24 Ok(())
25 }
26}
27
28impl error::Error for ErrorWithTrace {
29 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
30 self.error.inner.source()
31 }
32}
33
34#[derive(Debug)]
37pub struct BoxedError {
38 inner: ThinBox<dyn error::Error + Send + Sync + 'static>,
39}
40
41impl fmt::Display for BoxedError {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "{}", self.inner)
44 }
45}
46
47impl error::Error for BoxedError {
48 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
49 self.inner.source()
50 }
51}
52
53impl Trace for BoxedError {
54 fn trace<R>(self, trace: R) -> Self
55 where
56 R: fmt::Debug + fmt::Display + Send + Sync + 'static,
57 {
58 Self::new(ErrorWithTrace {
59 error: self,
60 trace: unsafe {
63 ThinBox::new_unchecked(trace, |ptr| ptr as *mut _)
64 },
65 })
66 }
67}
68
69impl Source for BoxedError {
70 fn new<T: error::Error + Send + Sync + 'static>(source: T) -> Self {
71 Self {
72 inner: unsafe {
75 ThinBox::new_unchecked(source, |ptr| ptr as *mut _)
76 },
77 }
78 }
79}