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 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 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 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 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 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 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 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 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 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}