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