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