1use std::{error, fmt, ops, panic::Location, sync::Arc};
2
3use crate::{Backtrace, Bytes, ErrorDiagnostic, ErrorMapping, ResultType, 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: error::Error> 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 fn typ(&self) -> ResultType {
197 self.inner.typ()
198 }
199
200 fn signature(&self) -> &'static str {
201 self.inner.signature()
202 }
203
204 fn tag(&self) -> Option<&Bytes> {
205 self.inner.tag()
206 }
207
208 fn service(&self) -> Option<&'static str> {
209 self.inner.service()
210 }
211
212 fn backtrace(&self) -> Option<&Backtrace> {
213 self.inner.backtrace()
214 }
215}
216
217impl<T, E, U> ErrorMapping<T, E, U> for Result<T, E>
218where
219 U: From<E>,
220{
221 fn into_error(self) -> Result<T, Error<U>> {
222 match self {
223 Ok(val) => Ok(val),
224 Err(err) => Err(Error {
225 inner: Arc::new(ErrorRepr::new3(
226 U::from(err),
227 None,
228 None,
229 Location::caller(),
230 )),
231 }),
232 }
233 }
234}
235
236impl<T, E, U> ErrorMapping<T, E, U> for Result<T, Error<E>>
237where
238 U: From<E>,
239 E: Clone,
240{
241 fn into_error(self) -> Result<T, Error<U>> {
242 match self {
243 Ok(val) => Ok(val),
244 Err(err) => Err(err.map(U::from)),
245 }
246 }
247}
248
249impl<E: fmt::Display> fmt::Display for Error<E> {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 fmt::Display::fmt(&self.inner.error, f)
252 }
253}
254
255impl<E: fmt::Debug> fmt::Debug for Error<E> {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 fmt::Debug::fmt(&self.inner.error, f)
258 }
259}
260
261struct ErrorDebug<'a, E> {
262 inner: &'a ErrorRepr<E>,
263}
264
265impl<E: fmt::Debug> fmt::Debug for ErrorDebug<'_, E> {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 f.debug_struct("Error")
268 .field("error", &self.inner.error)
269 .field("service", &self.inner.service)
270 .field("backtrace", &self.inner.backtrace)
271 .finish()
272 }
273}