1use std::{any::Any, any::TypeId, error, fmt, sync::Arc};
2
3use crate::{Backtrace, Error, ErrorDiagnostic, repr::ErrorRepr};
4
5trait ErrorInformation: fmt::Display + fmt::Debug + 'static {
6 fn tag(&self) -> Option<&crate::Bytes>;
7
8 fn service(&self) -> Option<&'static str>;
9
10 fn signature(&self) -> &'static str;
11
12 fn backtrace(&self) -> Option<&Backtrace>;
13
14 fn source(&self) -> Option<&(dyn error::Error + 'static)>;
15
16 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)>;
17}
18
19impl<E> ErrorInformation for ErrorRepr<E>
20where
21 E: ErrorDiagnostic + error::Error,
22{
23 fn tag(&self) -> Option<&crate::Bytes> {
24 ErrorDiagnostic::tag(self)
25 }
26
27 fn service(&self) -> Option<&'static str> {
28 ErrorDiagnostic::service(self)
29 }
30
31 fn signature(&self) -> &'static str {
32 self.error.signature()
33 }
34
35 fn backtrace(&self) -> Option<&Backtrace> {
36 ErrorDiagnostic::backtrace(self)
37 }
38
39 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
40 self.error.source()
41 }
42
43 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)> {
44 self.ext.map.get(id).map(AsRef::as_ref)
45 }
46}
47
48#[derive(Clone)]
52pub struct ErrorInfo {
53 inner: Arc<dyn ErrorInformation>,
54}
55
56impl ErrorInfo {
57 pub fn tag(&self) -> Option<&crate::Bytes> {
59 self.inner.tag()
60 }
61
62 pub fn service(&self) -> Option<&'static str> {
64 self.inner.service()
65 }
66
67 pub fn signature(&self) -> &'static str {
69 self.inner.signature()
70 }
71
72 pub fn backtrace(&self) -> Option<&Backtrace> {
74 self.inner.backtrace()
75 }
76
77 pub fn get_item<T: 'static>(&self) -> Option<&T> {
79 self.inner
80 .get_item(&TypeId::of::<T>())
81 .and_then(|boxed| boxed.downcast_ref())
82 }
83}
84
85impl<E> From<Error<E>> for ErrorInfo
86where
87 E: ErrorDiagnostic + error::Error,
88{
89 fn from(err: Error<E>) -> Self {
90 Self { inner: err.inner }
91 }
92}
93
94impl<E> From<&Error<E>> for ErrorInfo
95where
96 E: ErrorDiagnostic + error::Error,
97{
98 fn from(err: &Error<E>) -> Self {
99 Self {
100 inner: err.inner.clone(),
101 }
102 }
103}
104
105impl error::Error for ErrorInfo {
106 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
107 self.inner.source()
108 }
109}
110
111impl fmt::Debug for ErrorInfo {
112 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113 fmt::Debug::fmt(&self.inner, f)
114 }
115}
116
117impl fmt::Display for ErrorInfo {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 fmt::Display::fmt(&self.inner, f)
120 }
121}
122
123impl ErrorDiagnostic for ErrorInfo {
124 fn signature(&self) -> &'static str {
125 self.inner.signature()
126 }
127
128 fn service(&self) -> Option<&'static str> {
129 self.inner.service()
130 }
131
132 fn backtrace(&self) -> Option<&Backtrace> {
133 self.inner.backtrace()
134 }
135}