1use ntex_bytes::Bytes;
2use std::{any::Any, any::TypeId, error, fmt, sync::Arc};
3
4use crate::{AsError, Backtrace, Error, ErrorDiagnostic, IntoFailure, repr::ErrorRepr};
5
6trait ErrorInfo: fmt::Display + fmt::Debug + 'static {
7 fn tag(&self) -> Option<&crate::Bytes>;
8
9 fn service(&self) -> Option<&'static str>;
10
11 fn signature(&self) -> &'static str;
12
13 fn backtrace(&self) -> Option<&Backtrace>;
14
15 fn source(&self) -> Option<&(dyn error::Error + 'static)>;
16
17 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)>;
18}
19
20impl<E> ErrorInfo for ErrorRepr<E>
21where
22 E: ErrorDiagnostic,
23{
24 fn tag(&self) -> Option<&crate::Bytes> {
25 ErrorDiagnostic::tag(self)
26 }
27
28 fn service(&self) -> Option<&'static str> {
29 ErrorDiagnostic::service(self)
30 }
31
32 fn signature(&self) -> &'static str {
33 self.error.signature()
34 }
35
36 fn backtrace(&self) -> Option<&Backtrace> {
37 ErrorDiagnostic::backtrace(self)
38 }
39
40 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
41 self.error.source()
42 }
43
44 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)> {
45 self.ext.map.get(id).map(AsRef::as_ref)
46 }
47}
48
49pub struct Failure {
53 inner: FailureDiagnostic,
54}
55
56pub struct FailureDiagnostic(Arc<dyn ErrorInfo>);
57
58impl Failure {
59 pub fn tag(&self) -> Option<&crate::Bytes> {
61 self.inner.0.tag()
62 }
63
64 pub fn service(&self) -> Option<&'static str> {
66 self.inner.0.service()
67 }
68
69 pub fn signature(&self) -> &'static str {
71 self.inner.0.signature()
72 }
73
74 pub fn backtrace(&self) -> Option<&Backtrace> {
76 self.inner.0.backtrace()
77 }
78
79 pub fn get_item<T: 'static>(&self) -> Option<&T> {
81 self.inner
82 .0
83 .get_item(&TypeId::of::<T>())
84 .and_then(|boxed| boxed.downcast_ref())
85 }
86}
87
88impl<E> From<Error<E>> for Failure
89where
90 E: ErrorDiagnostic,
91{
92 fn from(err: Error<E>) -> Self {
93 Self {
94 inner: FailureDiagnostic(err.inner),
95 }
96 }
97}
98
99impl<E> From<&Error<E>> for Failure
100where
101 E: ErrorDiagnostic,
102{
103 fn from(err: &Error<E>) -> Self {
104 Self {
105 inner: FailureDiagnostic(err.inner.clone()),
106 }
107 }
108}
109
110impl IntoFailure for Failure {
111 fn fail(self) -> Failure {
112 self
113 }
114}
115
116impl<E> IntoFailure for E
117where
118 E: ErrorDiagnostic + Into<Error<E>>,
119{
120 fn fail(self) -> Failure {
121 Failure {
122 inner: FailureDiagnostic(self.into().inner),
123 }
124 }
125}
126
127impl error::Error for Failure {
128 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
129 self.inner.source()
130 }
131}
132
133impl fmt::Debug for Failure {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 fmt::Debug::fmt(&self.inner, f)
136 }
137}
138
139impl fmt::Display for Failure {
140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141 fmt::Display::fmt(&self.inner, f)
142 }
143}
144
145impl Clone for Failure {
146 fn clone(&self) -> Self {
147 Failure {
148 inner: FailureDiagnostic(self.inner.0.clone()),
149 }
150 }
151}
152
153impl AsError for Failure {
154 type Target = FailureDiagnostic;
155
156 fn as_diag(&self) -> &FailureDiagnostic {
157 &self.inner
158 }
159}
160
161impl ErrorDiagnostic for FailureDiagnostic {
162 fn signature(&self) -> &'static str {
163 self.0.signature()
164 }
165
166 fn tag(&self) -> Option<&Bytes> {
167 self.0.tag()
168 }
169
170 fn service(&self) -> Option<&'static str> {
171 self.0.service()
172 }
173
174 fn backtrace(&self) -> Option<&Backtrace> {
175 self.0.backtrace()
176 }
177}
178
179impl error::Error for FailureDiagnostic {
180 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
181 self.0.source()
182 }
183}
184
185impl fmt::Debug for FailureDiagnostic {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 fmt::Debug::fmt(&self.0, f)
188 }
189}
190
191impl fmt::Display for FailureDiagnostic {
192 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193 fmt::Display::fmt(&self.0, f)
194 }
195}