Skip to main content

ntex_error/
error.rs

1use std::{error, fmt, ops, panic::Location, sync::Arc};
2
3use crate::{Backtrace, ErrorDiagnostic, ErrorMapping, repr::ErrorRepr};
4
5pub struct Error<E> {
6    pub(crate) inner: Arc<ErrorRepr<E>>,
7}
8
9impl<E> Error<E> {
10    #[track_caller]
11    /// Create new error wrapper.
12    pub fn new<T>(error: T, service: &'static str) -> Self
13    where
14        E: From<T>,
15    {
16        Self {
17            inner: Arc::new(ErrorRepr::new3(
18                E::from(error),
19                Some(service),
20                Location::caller(),
21            )),
22        }
23    }
24
25    /// Map inner error to new error.
26    ///
27    /// Keep same `service` and `location`
28    pub fn forward<U, F>(self, f: F) -> Error<U>
29    where
30        F: FnOnce(Error<E>) -> U,
31    {
32        let svc = self.inner.service;
33        let bt = self.inner.backtrace.clone();
34        let ext = self.inner.ext.clone();
35
36        Error {
37            inner: Arc::new(ErrorRepr::new2(f(self), svc, bt, ext)),
38        }
39    }
40
41    /// Print error debug information.
42    pub fn debug(&self) -> impl fmt::Debug
43    where
44        E: fmt::Debug,
45    {
46        ErrorDebug {
47            inner: self.inner.as_ref(),
48        }
49    }
50
51    /// Get a reference to a type previously inserted on this `Error`.
52    pub fn get_item<T: 'static>(&self) -> Option<&T> {
53        self.inner.ext.get::<T>()
54    }
55}
56
57impl<E: Clone> Error<E> {
58    #[must_use]
59    /// Set error's responsible service.
60    pub fn set_service(mut self, name: &'static str) -> Self {
61        if let Some(inner) = Arc::get_mut(&mut self.inner) {
62            inner.service = Some(name);
63            self
64        } else {
65            Error {
66                inner: Arc::new(ErrorRepr::new2(
67                    self.inner.error.clone(),
68                    Some(name),
69                    self.inner.backtrace.clone(),
70                    self.inner.ext.clone(),
71                )),
72            }
73        }
74    }
75
76    /// Map inner error to new error.
77    ///
78    /// Keep same `service` and `location`
79    pub fn map<U, F>(self, f: F) -> Error<U>
80    where
81        F: FnOnce(E) -> U,
82    {
83        let (err, svc, bt, ext) = match Arc::try_unwrap(self.inner) {
84            Ok(inner) => (inner.error, inner.service, inner.backtrace, inner.ext),
85            Err(inner) => (
86                inner.error.clone(),
87                inner.service,
88                inner.backtrace.clone(),
89                inner.ext.clone(),
90            ),
91        };
92
93        Error {
94            inner: Arc::new(ErrorRepr::new2(f(err), svc, bt, ext)),
95        }
96    }
97
98    /// Try to map inner error to new error.
99    ///
100    /// Keep same `service` and `location`
101    pub fn try_map<T, U, F>(self, f: F) -> Result<T, Error<U>>
102    where
103        F: FnOnce(E) -> Result<T, U>,
104    {
105        let (err, svc, bt, ext) = match Arc::try_unwrap(self.inner) {
106            Ok(inner) => (inner.error, inner.service, inner.backtrace, inner.ext),
107            Err(inner) => (
108                inner.error.clone(),
109                inner.service,
110                inner.backtrace.clone(),
111                inner.ext.clone(),
112            ),
113        };
114
115        f(err).map_err(move |err| Error {
116            inner: Arc::new(ErrorRepr::new2(err, svc, bt, ext)),
117        })
118    }
119
120    #[must_use]
121    /// Insert a type into this `Error`.
122    pub fn insert_item<T: Sync + Send + 'static>(mut self, val: T) -> Self {
123        if let Some(inner) = Arc::get_mut(&mut self.inner) {
124            inner.ext.insert(val);
125            self
126        } else {
127            let mut ext = self.inner.ext.clone();
128            ext.insert(val);
129            Error {
130                inner: Arc::new(ErrorRepr::new2(
131                    self.inner.error.clone(),
132                    self.inner.service,
133                    self.inner.backtrace.clone(),
134                    ext,
135                )),
136            }
137        }
138    }
139}
140
141impl<E: Clone> Error<E> {
142    /// Get inner error value
143    pub fn into_error(self) -> E {
144        Arc::try_unwrap(self.inner)
145            .map_or_else(|inner| inner.error.clone(), |inner| inner.error)
146    }
147}
148
149impl<E> Clone for Error<E> {
150    fn clone(&self) -> Error<E> {
151        Error {
152            inner: self.inner.clone(),
153        }
154    }
155}
156
157impl<E> From<E> for Error<E> {
158    #[track_caller]
159    fn from(error: E) -> Self {
160        Self {
161            inner: Arc::new(ErrorRepr::new3(error, None, Location::caller())),
162        }
163    }
164}
165
166impl<E> Eq for Error<E> where E: Eq {}
167
168impl<E> PartialEq for Error<E>
169where
170    E: PartialEq,
171{
172    fn eq(&self, other: &Self) -> bool {
173        self.inner.error.eq(&other.inner.error) && self.inner.service == other.inner.service
174    }
175}
176
177impl<E> PartialEq<E> for Error<E>
178where
179    E: PartialEq,
180{
181    fn eq(&self, other: &E) -> bool {
182        self.inner.error.eq(other)
183    }
184}
185
186impl<E> ops::Deref for Error<E> {
187    type Target = E;
188
189    fn deref(&self) -> &E {
190        &self.inner.error
191    }
192}
193
194impl<E: error::Error + 'static> error::Error for Error<E> {
195    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
196        self.inner.error.source()
197    }
198}
199
200impl<E: ErrorDiagnostic> ErrorDiagnostic for Error<E> {
201    type Kind = E::Kind;
202
203    fn kind(&self) -> Self::Kind {
204        self.inner.kind()
205    }
206
207    fn service(&self) -> Option<&'static str> {
208        self.inner.service()
209    }
210
211    fn backtrace(&self) -> Option<&Backtrace> {
212        self.inner.backtrace()
213    }
214}
215
216impl<T, E, U> ErrorMapping<T, E, U> for Result<T, E>
217where
218    U: From<E>,
219{
220    fn into_error(self) -> Result<T, Error<U>> {
221        match self {
222            Ok(val) => Ok(val),
223            Err(err) => Err(Error {
224                inner: Arc::new(ErrorRepr::new3(U::from(err), None, Location::caller())),
225            }),
226        }
227    }
228}
229
230impl<T, E, U> ErrorMapping<T, E, U> for Result<T, Error<E>>
231where
232    U: From<E>,
233    E: Clone,
234{
235    fn into_error(self) -> Result<T, Error<U>> {
236        match self {
237            Ok(val) => Ok(val),
238            Err(err) => Err(err.map(U::from)),
239        }
240    }
241}
242
243impl<E: fmt::Display> fmt::Display for Error<E> {
244    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245        fmt::Display::fmt(&self.inner.error, f)
246    }
247}
248
249impl<E: fmt::Debug> fmt::Debug for Error<E> {
250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251        fmt::Debug::fmt(&self.inner.error, f)
252    }
253}
254
255struct ErrorDebug<'a, E> {
256    inner: &'a ErrorRepr<E>,
257}
258
259impl<E: fmt::Debug> fmt::Debug for ErrorDebug<'_, E> {
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        f.debug_struct("Error")
262            .field("error", &self.inner.error)
263            .field("service", &self.inner.service)
264            .field("backtrace", &self.inner.backtrace)
265            .finish()
266    }
267}