1use std::{error, fmt, ops, panic::Location, sync::Arc};
2
3use crate::{AsError, Backtrace, Bytes, ErrorDiagnostic, ErrorMapping, repr::ErrorRepr};
4
5pub struct Error<E> {
11 pub(crate) inner: Arc<ErrorRepr<E>>,
12}
13
14impl<E> Error<E> {
15 #[track_caller]
19 pub fn new<T>(error: T, service: &'static str) -> Self
20 where
21 E: From<T>,
22 {
23 Self {
24 inner: Arc::new(ErrorRepr::new3(
25 E::from(error),
26 None,
27 Some(service),
28 Location::caller(),
29 )),
30 }
31 }
32
33 #[track_caller]
37 pub fn from_err<T>(error: T) -> Self
38 where
39 E: From<T>,
40 {
41 Self {
42 inner: Arc::new(ErrorRepr::new3(
43 error.into(),
44 None,
45 None,
46 Location::caller(),
47 )),
48 }
49 }
50
51 pub fn forward<U, F>(self, f: F) -> Error<U>
55 where
56 F: FnOnce(Error<E>) -> U,
57 {
58 let svc = self.inner.service;
59 let tag = self.inner.tag.clone();
60 let bt = self.inner.backtrace.clone();
61 let ext = self.inner.ext.clone();
62
63 Error {
64 inner: Arc::new(ErrorRepr::new2(f(self), tag, svc, bt, ext)),
65 }
66 }
67
68 pub fn debug(&self) -> impl fmt::Debug
72 where
73 E: fmt::Debug,
74 {
75 ErrorDebug {
76 inner: self.inner.as_ref(),
77 }
78 }
79
80 pub fn get_item<T: 'static>(&self) -> Option<&T> {
84 self.inner.ext.get::<T>()
85 }
86}
87
88impl<E: Clone> Error<E> {
89 #[must_use]
93 pub fn set_tag<T: Into<Bytes>>(self, tag: T) -> Self {
94 Error {
95 inner: ErrorRepr::with_mut(self.inner, move |inner| {
96 inner.tag = Some(tag.into());
97 }),
98 }
99 }
100
101 #[must_use]
105 pub fn set_service(self, name: &'static str) -> Self {
106 Error {
107 inner: ErrorRepr::with_mut(self.inner, move |inner| {
108 inner.service = Some(name);
109 }),
110 }
111 }
112
113 pub fn map<U, F>(self, f: F) -> Error<U>
117 where
118 F: FnOnce(E) -> U,
119 {
120 let (err, tag, svc, bt, ext) = ErrorRepr::unpack(self.inner);
121
122 Error {
123 inner: Arc::new(ErrorRepr::new2(f(err), tag, svc, bt, ext)),
124 }
125 }
126
127 pub fn map_err<U>(self) -> Error<U>
131 where
132 U: From<E>,
133 {
134 let (err, tag, svc, bt, ext) = ErrorRepr::unpack(self.inner);
135
136 Error {
137 inner: Arc::new(ErrorRepr::new2(err.into(), tag, svc, bt, ext)),
138 }
139 }
140
141 pub fn try_map<T, U, F>(self, f: F) -> Result<T, Error<U>>
145 where
146 F: FnOnce(E) -> Result<T, U>,
147 {
148 let (err, tag, svc, bt, ext) = ErrorRepr::unpack(self.inner);
149
150 f(err).map_err(move |err| Error {
151 inner: Arc::new(ErrorRepr::new2(err, tag, svc, bt, ext)),
152 })
153 }
154
155 #[must_use]
159 pub fn insert_item<T: Sync + Send + 'static>(self, val: T) -> Self {
160 Error {
161 inner: ErrorRepr::with_mut(self.inner, move |inner| {
162 inner.ext.insert(val);
163 }),
164 }
165 }
166}
167
168impl<E: Clone> Error<E> {
169 pub fn into_error(self) -> E {
171 Arc::try_unwrap(self.inner).map_or_else(|inner| inner.error.clone(), |inner| inner.error)
172 }
173}
174
175impl<E> Clone for Error<E> {
176 fn clone(&self) -> Error<E> {
177 Error {
178 inner: self.inner.clone(),
179 }
180 }
181}
182
183impl<E: error::Error> From<E> for Error<E> {
184 #[track_caller]
185 fn from(error: E) -> Self {
186 Self {
187 inner: Arc::new(ErrorRepr::new3(error, None, None, Location::caller())),
188 }
189 }
190}
191
192impl<E> Eq for Error<E> where E: Eq {}
193
194impl<E> PartialEq for Error<E>
195where
196 E: PartialEq,
197{
198 fn eq(&self, other: &Self) -> bool {
199 self.inner.error.eq(&other.inner.error) && self.inner.service == other.inner.service
200 }
201}
202
203impl<E> PartialEq<E> for Error<E>
204where
205 E: PartialEq,
206{
207 fn eq(&self, other: &E) -> bool {
208 self.inner.error.eq(other)
209 }
210}
211
212impl<E> ops::Deref for Error<E> {
213 type Target = E;
214
215 fn deref(&self) -> &E {
216 &self.inner.error
217 }
218}
219
220impl<E: error::Error + 'static> error::Error for Error<E> {
221 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
222 self.inner.error.source()
223 }
224}
225
226impl<E: ErrorDiagnostic> AsError for Error<E> {
227 type Target = E;
228
229 fn as_diag(&self) -> &E {
230 self
231 }
232}
233
234impl<E: ErrorDiagnostic> ErrorDiagnostic for Error<E> {
235 fn signature(&self) -> &'static str {
236 self.inner.signature()
237 }
238
239 fn tag(&self) -> Option<&Bytes> {
240 self.inner.tag()
241 }
242
243 fn service(&self) -> Option<&'static str> {
244 self.inner.service()
245 }
246
247 fn backtrace(&self) -> Option<&Backtrace> {
248 self.inner.backtrace()
249 }
250}
251
252impl<T, E, U> ErrorMapping<T, E, U> for Result<T, E>
253where
254 U: From<E>,
255{
256 fn into_error(self) -> Result<T, Error<U>> {
257 match self {
258 Ok(val) => Ok(val),
259 Err(err) => Err(Error {
260 inner: Arc::new(ErrorRepr::new3(
261 U::from(err),
262 None,
263 None,
264 Location::caller(),
265 )),
266 }),
267 }
268 }
269}
270
271impl<T, E, U> ErrorMapping<T, E, U> for Result<T, Error<E>>
272where
273 U: From<E>,
274 E: Clone,
275{
276 fn into_error(self) -> Result<T, Error<U>> {
277 match self {
278 Ok(val) => Ok(val),
279 Err(err) => Err(err.map(U::from)),
280 }
281 }
282}
283
284impl<E: fmt::Display> fmt::Display for Error<E> {
285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
286 fmt::Display::fmt(&self.inner.error, f)
287 }
288}
289
290impl<E: fmt::Debug> fmt::Debug for Error<E> {
291 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292 fmt::Debug::fmt(&self.inner.error, f)
293 }
294}
295
296struct ErrorDebug<'a, E> {
297 inner: &'a ErrorRepr<E>,
298}
299
300impl<E: fmt::Debug> fmt::Debug for ErrorDebug<'_, E> {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 f.debug_struct("Error")
303 .field("error", &self.inner.error)
304 .field("service", &self.inner.service)
305 .field("tag", &self.inner.tag)
306 .field("backtrace", &self.inner.backtrace)
307 .finish()
308 }
309}