1use std::{error, fmt, ops, panic::Location, sync::Arc};
2
3use crate::{Backtrace, 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 Some(service),
27 Location::caller(),
28 )),
29 }
30 }
31
32 pub fn forward<U, F>(self, f: F) -> Error<U>
36 where
37 F: FnOnce(Error<E>) -> U,
38 {
39 let svc = self.inner.service;
40 let bt = self.inner.backtrace.clone();
41 let ext = self.inner.ext.clone();
42
43 Error {
44 inner: Arc::new(ErrorRepr::new2(f(self), svc, bt, ext)),
45 }
46 }
47
48 pub fn debug(&self) -> impl fmt::Debug
52 where
53 E: fmt::Debug,
54 {
55 ErrorDebug {
56 inner: self.inner.as_ref(),
57 }
58 }
59
60 pub fn get_item<T: 'static>(&self) -> Option<&T> {
64 self.inner.ext.get::<T>()
65 }
66}
67
68impl<E: Clone> Error<E> {
69 #[must_use]
73 pub fn set_service(mut self, name: &'static str) -> Self {
74 if let Some(inner) = Arc::get_mut(&mut self.inner) {
75 inner.service = Some(name);
76 self
77 } else {
78 Error {
79 inner: Arc::new(ErrorRepr::new2(
80 self.inner.error.clone(),
81 Some(name),
82 self.inner.backtrace.clone(),
83 self.inner.ext.clone(),
84 )),
85 }
86 }
87 }
88
89 pub fn map<U, F>(self, f: F) -> Error<U>
93 where
94 F: FnOnce(E) -> U,
95 {
96 let (err, svc, bt, ext) = match Arc::try_unwrap(self.inner) {
97 Ok(inner) => (inner.error, inner.service, inner.backtrace, inner.ext),
98 Err(inner) => (
99 inner.error.clone(),
100 inner.service,
101 inner.backtrace.clone(),
102 inner.ext.clone(),
103 ),
104 };
105
106 Error {
107 inner: Arc::new(ErrorRepr::new2(f(err), svc, bt, ext)),
108 }
109 }
110
111 pub fn try_map<T, U, F>(self, f: F) -> Result<T, Error<U>>
115 where
116 F: FnOnce(E) -> Result<T, U>,
117 {
118 let (err, svc, bt, ext) = match Arc::try_unwrap(self.inner) {
119 Ok(inner) => (inner.error, inner.service, inner.backtrace, inner.ext),
120 Err(inner) => (
121 inner.error.clone(),
122 inner.service,
123 inner.backtrace.clone(),
124 inner.ext.clone(),
125 ),
126 };
127
128 f(err).map_err(move |err| Error {
129 inner: Arc::new(ErrorRepr::new2(err, svc, bt, ext)),
130 })
131 }
132
133 #[must_use]
137 pub fn insert_item<T: Sync + Send + 'static>(mut self, val: T) -> Self {
138 if let Some(inner) = Arc::get_mut(&mut self.inner) {
139 inner.ext.insert(val);
140 self
141 } else {
142 let mut ext = self.inner.ext.clone();
143 ext.insert(val);
144 Error {
145 inner: Arc::new(ErrorRepr::new2(
146 self.inner.error.clone(),
147 self.inner.service,
148 self.inner.backtrace.clone(),
149 ext,
150 )),
151 }
152 }
153 }
154}
155
156impl<E: Clone> Error<E> {
157 pub fn into_error(self) -> E {
159 Arc::try_unwrap(self.inner)
160 .map_or_else(|inner| inner.error.clone(), |inner| inner.error)
161 }
162}
163
164impl<E> Clone for Error<E> {
165 fn clone(&self) -> Error<E> {
166 Error {
167 inner: self.inner.clone(),
168 }
169 }
170}
171
172impl<E> From<E> for Error<E> {
173 #[track_caller]
174 fn from(error: E) -> Self {
175 Self {
176 inner: Arc::new(ErrorRepr::new3(error, None, Location::caller())),
177 }
178 }
179}
180
181impl<E> Eq for Error<E> where E: Eq {}
182
183impl<E> PartialEq for Error<E>
184where
185 E: PartialEq,
186{
187 fn eq(&self, other: &Self) -> bool {
188 self.inner.error.eq(&other.inner.error) && self.inner.service == other.inner.service
189 }
190}
191
192impl<E> PartialEq<E> for Error<E>
193where
194 E: PartialEq,
195{
196 fn eq(&self, other: &E) -> bool {
197 self.inner.error.eq(other)
198 }
199}
200
201impl<E> ops::Deref for Error<E> {
202 type Target = E;
203
204 fn deref(&self) -> &E {
205 &self.inner.error
206 }
207}
208
209impl<E: error::Error + 'static> error::Error for Error<E> {
210 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
211 self.inner.error.source()
212 }
213}
214
215impl<E: ErrorDiagnostic> ErrorDiagnostic for Error<E> {
216 type Kind = E::Kind;
217
218 fn kind(&self) -> Self::Kind {
219 self.inner.kind()
220 }
221
222 fn service(&self) -> Option<&'static str> {
223 self.inner.service()
224 }
225
226 fn backtrace(&self) -> Option<&Backtrace> {
227 self.inner.backtrace()
228 }
229}
230
231impl<T, E, U> ErrorMapping<T, E, U> for Result<T, E>
232where
233 U: From<E>,
234{
235 fn into_error(self) -> Result<T, Error<U>> {
236 match self {
237 Ok(val) => Ok(val),
238 Err(err) => Err(Error {
239 inner: Arc::new(ErrorRepr::new3(U::from(err), None, Location::caller())),
240 }),
241 }
242 }
243}
244
245impl<T, E, U> ErrorMapping<T, E, U> for Result<T, Error<E>>
246where
247 U: From<E>,
248 E: Clone,
249{
250 fn into_error(self) -> Result<T, Error<U>> {
251 match self {
252 Ok(val) => Ok(val),
253 Err(err) => Err(err.map(U::from)),
254 }
255 }
256}
257
258impl<E: fmt::Display> fmt::Display for Error<E> {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 fmt::Display::fmt(&self.inner.error, f)
261 }
262}
263
264impl<E: fmt::Debug> fmt::Debug for Error<E> {
265 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266 fmt::Debug::fmt(&self.inner.error, f)
267 }
268}
269
270struct ErrorDebug<'a, E> {
271 inner: &'a ErrorRepr<E>,
272}
273
274impl<E: fmt::Debug> fmt::Debug for ErrorDebug<'_, E> {
275 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276 f.debug_struct("Error")
277 .field("error", &self.inner.error)
278 .field("service", &self.inner.service)
279 .field("backtrace", &self.inner.backtrace)
280 .finish()
281 }
282}