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
12 where
13 E: From<T>,
14 {
15 Self {
16 inner: Arc::new(ErrorRepr::new3(
17 E::from(error),
18 Some(service),
19 Location::caller(),
20 )),
21 }
22 }
23
24 #[must_use]
25 pub fn set_service(mut self, name: &'static str) -> Self
27 where
28 E: Clone,
29 {
30 if let Some(inner) = Arc::get_mut(&mut self.inner) {
31 inner.service = Some(name);
32 self
33 } else {
34 Error {
35 inner: Arc::new(ErrorRepr::new2(
36 self.inner.error.clone(),
37 Some(name),
38 self.inner.backtrace.clone(),
39 )),
40 }
41 }
42 }
43
44 pub fn map<U, F>(self, f: F) -> Error<U>
48 where
49 E: Clone,
50 F: FnOnce(E) -> U,
51 {
52 let (err, svc, bt) = match Arc::try_unwrap(self.inner) {
53 Ok(inner) => (inner.error, inner.service, inner.backtrace),
54 Err(inner) => (inner.error.clone(), inner.service, inner.backtrace.clone()),
55 };
56
57 Error {
58 inner: Arc::new(ErrorRepr::new2(f(err), svc, bt)),
59 }
60 }
61
62 pub fn forward<U, F>(self, f: F) -> Error<U>
66 where
67 F: FnOnce(Error<E>) -> U,
68 {
69 let svc = self.inner.service;
70 let bt = self.inner.backtrace.clone();
71
72 Error {
73 inner: Arc::new(ErrorRepr::new2(f(self), svc, bt)),
74 }
75 }
76
77 pub fn try_map<T, U, F>(self, f: F) -> Result<T, Error<U>>
81 where
82 E: Clone,
83 F: FnOnce(E) -> Result<T, U>,
84 {
85 let (err, svc, bt) = match Arc::try_unwrap(self.inner) {
86 Ok(inner) => (inner.error, inner.service, inner.backtrace),
87 Err(inner) => (inner.error.clone(), inner.service, inner.backtrace.clone()),
88 };
89
90 f(err).map_err(move |err| Error {
91 inner: Arc::new(ErrorRepr::new2(err, svc, bt)),
92 })
93 }
94
95 pub fn debug(&self) -> impl fmt::Debug
97 where
98 E: fmt::Debug,
99 {
100 ErrorDebug {
101 inner: self.inner.as_ref(),
102 }
103 }
104}
105
106impl<E: Clone> Error<E> {
107 pub fn into_error(self) -> E {
109 Arc::try_unwrap(self.inner)
110 .map_or_else(|inner| inner.error.clone(), |inner| inner.error)
111 }
112}
113
114impl<E> Clone for Error<E> {
115 fn clone(&self) -> Error<E> {
116 Error {
117 inner: self.inner.clone(),
118 }
119 }
120}
121
122impl<E> From<E> for Error<E> {
123 #[track_caller]
124 fn from(error: E) -> Self {
125 Self {
126 inner: Arc::new(ErrorRepr::new3(error, None, Location::caller())),
127 }
128 }
129}
130
131impl<E> Eq for Error<E> where E: Eq {}
132
133impl<E> PartialEq for Error<E>
134where
135 E: PartialEq,
136{
137 fn eq(&self, other: &Self) -> bool {
138 self.inner.error.eq(&other.inner.error) && self.inner.service == other.inner.service
139 }
140}
141
142impl<E> PartialEq<E> for Error<E>
143where
144 E: PartialEq,
145{
146 fn eq(&self, other: &E) -> bool {
147 self.inner.error.eq(other)
148 }
149}
150
151impl<E> ops::Deref for Error<E> {
152 type Target = E;
153
154 fn deref(&self) -> &E {
155 &self.inner.error
156 }
157}
158
159impl<E: error::Error + 'static> error::Error for Error<E> {
160 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
161 Some(&self.inner.error)
162 }
163}
164
165impl<E: ErrorDiagnostic> ErrorDiagnostic for Error<E> {
166 type Kind = E::Kind;
167
168 fn kind(&self) -> Self::Kind {
169 self.inner.kind()
170 }
171
172 fn service(&self) -> Option<&'static str> {
173 self.inner.service()
174 }
175
176 fn backtrace(&self) -> Option<&Backtrace> {
177 self.inner.backtrace()
178 }
179}
180
181impl<T, E, U> ErrorMapping<T, E, U> for Result<T, E>
182where
183 U: From<E>,
184{
185 fn into_error(self) -> Result<T, Error<U>> {
186 match self {
187 Ok(val) => Ok(val),
188 Err(err) => Err(Error {
189 inner: Arc::new(ErrorRepr::new3(U::from(err), None, Location::caller())),
190 }),
191 }
192 }
193}
194
195impl<T, E, U> ErrorMapping<T, E, U> for Result<T, Error<E>>
196where
197 U: From<E>,
198 E: Clone,
199{
200 fn into_error(self) -> Result<T, Error<U>> {
201 match self {
202 Ok(val) => Ok(val),
203 Err(err) => Err(err.map(U::from)),
204 }
205 }
206}
207
208impl<E: fmt::Display> fmt::Display for Error<E> {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 fmt::Display::fmt(&self.inner.error, f)
211 }
212}
213
214impl<E: fmt::Debug> fmt::Debug for Error<E> {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 fmt::Debug::fmt(&self.inner.error, f)
217 }
218}
219
220struct ErrorDebug<'a, E> {
221 inner: &'a ErrorRepr<E>,
222}
223
224impl<E: fmt::Debug> fmt::Debug for ErrorDebug<'_, E> {
225 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226 f.debug_struct("Error")
227 .field("error", &self.inner.error)
228 .field("service", &self.inner.service)
229 .field("backtrace", &self.inner.backtrace)
230 .finish()
231 }
232}