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>);
60
61impl Failure {
62 pub fn tag(&self) -> Option<&crate::Bytes> {
64 self.inner.0.tag()
65 }
66
67 pub fn service(&self) -> Option<&'static str> {
69 self.inner.0.service()
70 }
71
72 pub fn signature(&self) -> &'static str {
74 self.inner.0.signature()
75 }
76
77 pub fn backtrace(&self) -> Option<&Backtrace> {
79 self.inner.0.backtrace()
80 }
81
82 pub fn get_item<T: 'static>(&self) -> Option<&T> {
84 self.inner
85 .0
86 .get_item(&TypeId::of::<T>())
87 .and_then(|boxed| boxed.downcast_ref())
88 }
89}
90
91impl<E> From<Error<E>> for Failure
92where
93 E: ErrorDiagnostic,
94{
95 fn from(err: Error<E>) -> Self {
96 Self {
97 inner: FailureDiagnostic(err.inner),
98 }
99 }
100}
101
102impl<E> From<&Error<E>> for Failure
103where
104 E: ErrorDiagnostic,
105{
106 fn from(err: &Error<E>) -> Self {
107 Self {
108 inner: FailureDiagnostic(err.inner.clone()),
109 }
110 }
111}
112
113impl<E> IntoFailure for E
114where
115 E: ErrorDiagnostic + Into<Error<E>>,
116{
117 #[track_caller]
118 fn fail(self) -> Failure {
119 self.into_failure()
120 }
121}
122
123impl error::Error for Failure {
124 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
125 self.inner.source()
126 }
127}
128
129impl fmt::Debug for Failure {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 fmt::Debug::fmt(&self.inner, f)
132 }
133}
134
135impl fmt::Display for Failure {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 fmt::Display::fmt(&self.inner, f)
138 }
139}
140
141impl Clone for Failure {
142 fn clone(&self) -> Self {
143 Failure {
144 inner: FailureDiagnostic(self.inner.0.clone()),
145 }
146 }
147}
148
149impl AsError for Failure {
150 type Target = FailureDiagnostic;
151
152 fn as_diag(&self) -> &FailureDiagnostic {
153 &self.inner
154 }
155}
156
157impl ErrorDiagnostic for Failure {
158 fn signature(&self) -> &'static str {
159 self.inner.0.signature()
160 }
161
162 fn tag(&self) -> Option<&Bytes> {
163 self.inner.0.tag()
164 }
165
166 fn service(&self) -> Option<&'static str> {
167 self.inner.0.service()
168 }
169
170 fn backtrace(&self) -> Option<&Backtrace> {
171 self.inner.0.backtrace()
172 }
173
174 fn into_failure(self) -> Failure {
175 self
176 }
177}
178
179impl ErrorDiagnostic for FailureDiagnostic {
180 fn signature(&self) -> &'static str {
181 self.0.signature()
182 }
183
184 fn tag(&self) -> Option<&Bytes> {
185 self.0.tag()
186 }
187
188 fn service(&self) -> Option<&'static str> {
189 self.0.service()
190 }
191
192 fn backtrace(&self) -> Option<&Backtrace> {
193 self.0.backtrace()
194 }
195}
196
197impl error::Error for FailureDiagnostic {
198 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
199 self.0.source()
200 }
201}
202
203impl fmt::Debug for FailureDiagnostic {
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 fmt::Debug::fmt(&self.0, f)
206 }
207}
208
209impl fmt::Display for FailureDiagnostic {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 fmt::Display::fmt(&self.0, f)
212 }
213}