1use std::error::Error as StdError;
2use std::fmt;
3
4pub type Result<T> = std::result::Result<T, Error>;
6
7pub struct Error {
9 inner: anyhow::Error,
11 fields: Vec<(&'static str, Box<str>)>,
13}
14
15impl Error {
16 pub const fn new(error: anyhow::Error) -> Self {
18 Self {
19 inner: error,
20 fields: Vec::new(),
21 }
22 }
23
24 pub fn msg<T: fmt::Display + fmt::Debug + Send + Sync + 'static>(msg: T) -> Self {
26 Self::new(anyhow::Error::msg(msg))
27 }
28
29 pub fn with_field<V: fmt::Display>(mut self, key: &'static str, value: V) -> Self {
31 self.fields.push((key, value.to_string().into_boxed_str()));
32 self
33 }
34
35 pub fn with_field_debug<V: fmt::Debug>(mut self, key: &'static str, value: V) -> Self {
37 self.fields
38 .push((key, format!("{:?}", value).into_boxed_str()));
39 self
40 }
41
42 pub fn fields(&self) -> &[(&'static str, Box<str>)] {
44 &self.fields
45 }
46
47 pub fn get_field(&self, key: &str) -> Option<&str> {
49 self.fields
50 .iter()
51 .find(|(k, _)| *k == key)
52 .map(|(_, v)| v.as_ref())
53 }
54
55 pub fn context<C: fmt::Display + Send + Sync + 'static>(self, context: C) -> Self {
57 Self {
58 inner: self.inner.context(context),
59 fields: self.fields,
60 }
61 }
62
63 pub fn with_context<C, F>(self, f: F) -> Self
65 where
66 C: fmt::Display + Send + Sync + 'static,
67 F: FnOnce() -> C,
68 {
69 Self {
70 inner: self.inner.context(f()),
71 fields: self.fields,
72 }
73 }
74
75 pub fn root_cause(&self) -> &dyn StdError {
77 self.inner.root_cause()
78 }
79
80 pub fn chain(&self) -> anyhow::Chain {
82 self.inner.chain()
83 }
84
85 pub fn downcast<E>(self) -> std::result::Result<E, Self>
87 where
88 E: fmt::Display + fmt::Debug + Send + Sync + 'static,
89 {
90 match self.inner.downcast::<E>() {
91 Ok(e) => Ok(e),
92 Err(inner) => Err(Self {
93 inner,
94 fields: self.fields,
95 }),
96 }
97 }
98
99 pub fn downcast_ref<E>(&self) -> Option<&E>
101 where
102 E: fmt::Display + fmt::Debug + Send + Sync + 'static,
103 {
104 self.inner.downcast_ref::<E>()
105 }
106
107 pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
109 where
110 E: fmt::Display + fmt::Debug + Send + Sync + 'static,
111 {
112 self.inner.downcast_mut::<E>()
113 }
114
115 pub fn is<E>(&self) -> bool
117 where
118 E: fmt::Display + fmt::Debug + Send + Sync + 'static,
119 {
120 self.inner.is::<E>()
121 }
122}
123
124impl fmt::Display for Error {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "{}", self.inner)?;
128
129 if !self.fields.is_empty() {
131 write!(f, " [")?;
132 for (i, (key, value)) in self.fields.iter().enumerate() {
133 if i > 0 {
134 write!(f, ", ")?;
135 }
136 write!(f, "{}={}", key, value)?;
137 }
138 write!(f, "]")?;
139 }
140
141 Ok(())
142 }
143}
144
145impl fmt::Debug for Error {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(f, "{:?}", self.inner)?;
149
150 if !self.fields.is_empty() {
152 write!(f, "\n\nFields:\n")?;
153 for (i, (key, value)) in self.fields.iter().enumerate() {
154 write!(f, "\t{}: {:?}", key, value)?;
155 if i < self.fields.len().saturating_sub(1) {
156 write!(f, ",")?;
157 }
158 writeln!(f)?;
159 }
160 }
161
162 Ok(())
163 }
164}
165
166impl StdError for Error {
167 fn source(&self) -> Option<&(dyn StdError + 'static)> {
168 self.inner.source()
169 }
170}
171
172impl From<anyhow::Error> for Error {
173 fn from(error: anyhow::Error) -> Self {
174 Self::new(error)
175 }
176}
177
178impl From<String> for Error {
179 fn from(msg: String) -> Self {
180 Self::msg(msg)
181 }
182}
183
184impl From<&str> for Error {
185 fn from(msg: &str) -> Self {
186 Self::msg(msg.to_string())
187 }
188}
189
190pub trait Context<T> {
192 fn context<C>(self, context: C) -> Result<T>
194 where
195 C: fmt::Display + fmt::Debug + Send + Sync + 'static;
196
197 fn with_context<C, F>(self, f: F) -> Result<T>
199 where
200 C: fmt::Display + fmt::Debug + Send + Sync + 'static,
201 F: FnOnce() -> C;
202
203 fn with_field<V>(self, key: &'static str, value: V) -> Result<T>
205 where
206 V: fmt::Display;
207
208 fn with_field_debug<V>(self, key: &'static str, value: V) -> Result<T>
210 where
211 V: fmt::Debug;
212}
213
214impl<T, E> Context<T> for std::result::Result<T, E>
215where
216 E: std::error::Error + Send + Sync + 'static,
217{
218 fn context<C>(self, context: C) -> Result<T>
219 where
220 C: fmt::Display + fmt::Debug + Send + Sync + 'static,
221 {
222 self.map_err(|e| Error::from(anyhow::Error::from(e)).context(context))
223 }
224
225 fn with_context<C, F>(self, f: F) -> Result<T>
226 where
227 C: fmt::Display + fmt::Debug + Send + Sync + 'static,
228 F: FnOnce() -> C,
229 {
230 self.map_err(|e| Error::from(anyhow::Error::from(e)).with_context(f))
231 }
232
233 fn with_field<V>(self, key: &'static str, value: V) -> Result<T>
234 where
235 V: fmt::Display,
236 {
237 self.map_err(|e| Error::from(anyhow::Error::from(e)).with_field(key, value))
238 }
239
240 fn with_field_debug<V>(self, key: &'static str, value: V) -> Result<T>
241 where
242 V: fmt::Debug,
243 {
244 self.map_err(|e| Error::from(anyhow::Error::from(e)).with_field_debug(key, value))
245 }
246}
247
248impl<T> Context<T> for Option<T> {
249 fn context<C>(self, context: C) -> Result<T>
250 where
251 C: fmt::Display + fmt::Debug + Send + Sync + 'static,
252 {
253 self.ok_or_else(|| Error::msg(context))
254 }
255
256 fn with_context<C, F>(self, f: F) -> Result<T>
257 where
258 C: fmt::Display + fmt::Debug + Send + Sync + 'static,
259 F: FnOnce() -> C,
260 {
261 self.ok_or_else(|| Error::msg(f()))
262 }
263
264 fn with_field<V>(self, key: &'static str, value: V) -> Result<T>
265 where
266 V: fmt::Display,
267 {
268 self.ok_or_else(|| Error::msg("None value").with_field(key, value))
269 }
270
271 fn with_field_debug<V>(self, key: &'static str, value: V) -> Result<T>
272 where
273 V: fmt::Debug,
274 {
275 self.ok_or_else(|| Error::msg("None value").with_field_debug(key, value))
276 }
277}