1pub use core::error::Error as ErrorTrait;
2use core::panic::Location;
3use core::fmt::{ self, Debug, Display };
4
5pub mod prelude;
6#[cfg(feature = "axum-0-8")]
7mod axum_0_8;
8
9pub struct Err<E> {
10 frame: Box<TypedFrame<E>>
12}
13
14impl<E> Err<E>
15where
16 E: ErrorTrait + Send + Sync + 'static
17{
18 #[inline]
19 #[track_caller]
20 pub fn from_err(err: E) -> Self {
21 let children = walk(&err);
22
23 Err {
24 frame: Box::new(TypedFrame {
25 err,
26 location: Location::caller(),
27 children
28 })
29 }
30 }
31
32 #[inline]
33 #[track_caller]
34 pub fn from_errs<C>(err: E, children: &mut dyn Iterator<Item = C>) -> Self
35 where
36 C: ErrorTrait + Send + Sync + 'static
37 {
38 let (len, _) = children.size_hint();
39 let mut processed_children = Vec::with_capacity(len);
40 for err in children {
41 let children = walk(&err);
42
43 processed_children.push(Frame {
44 err: Box::new(err),
45 location: Location::caller(),
46 children
47 });
48 }
49
50 Err {
51 frame: Box::new(TypedFrame {
52 err,
53 location: Location::caller(),
54 children: processed_children
55 })
56 }
57 }
58
59 #[inline]
60 #[track_caller]
61 pub fn raise<E2>(self, err: E2) -> Err<E2>
62 where
63 E2: ErrorTrait + Send + Sync + 'static
64 {
65 let mut new = Err::from_err(err);
66 new.frame.children.push((*self.frame).into());
67 new
68 }
69
70 #[inline]
71 pub fn as_inner(&self) -> &E {
72 &self.frame.err
73 }
74
75 #[inline]
76 pub fn simple_display(&self) -> SimpleDisplay<'_, E> {
77 SimpleDisplay { inner: self }
78 }
79
80 #[inline]
81 pub fn detailed_display(&self) -> DetailedDisplay<'_, E> {
82 DetailedDisplay { inner: self }
83 }
84
85 #[inline]
86 pub fn as_error(&self) -> ErrorImplementorBorrowed<'_, E> {
87 ErrorImplementorBorrowed { inner: self }
88 }
89
90 #[inline]
91 pub fn into_error(self) -> ErrorImplementorOwned<E> {
92 ErrorImplementorOwned { inner: self }
93 }
94}
95
96impl<E> Debug for Err<E>
97where
98 E: ErrorTrait + Send + Sync + 'static
99{
100 #[inline]
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 self.detailed_display().fmt(f)
103 }
104}
105
106struct TypedFrame<E> {
107 err: E,
108 location: &'static Location<'static>,
109 children: Vec<Frame>
110}
111
112struct Frame {
113 err: Box<dyn ErrorTrait + Send + Sync + 'static>,
114 location: &'static Location<'static>,
115 children: Vec<Frame>
116}
117
118impl<E> From<TypedFrame<E>> for Frame
119where
120 E: ErrorTrait + Send + Sync + 'static
121{
122 #[inline]
123 fn from(frame: TypedFrame<E>) -> Self {
124 let TypedFrame { err, location, children } = frame;
125 let err = Box::new(err);
126 Frame { err, location, children }
127 }
128}
129
130struct BorrowedFrame<'h> {
131 err: &'h (dyn ErrorTrait + Send + Sync + 'static),
132 location: &'static Location<'static>,
133 children: &'h [Frame]
134}
135
136impl<'h, E> From<&'h TypedFrame<E>> for BorrowedFrame<'h>
137where
138 E: ErrorTrait + Send + Sync + 'static
139{
140 #[inline]
141 fn from(frame: &'h TypedFrame<E>) -> Self {
142 let TypedFrame { err, location, children } = frame;
143 Self { err, location, children }
144 }
145}
146
147impl<'h> From<&'h Frame> for BorrowedFrame<'h> {
148 #[inline]
149 fn from(frame: &'h Frame) -> Self {
150 let Frame { err, location, children } = frame;
151 Self { err: &**err, location, children }
152 }
153}
154
155pub struct SimpleDisplay<'h, E> {
156 inner: &'h Err<E>
157}
158
159impl<'h, E> Display for SimpleDisplay<'h, E>
160where
161 E: ErrorTrait + Send + Sync + 'static
162{
163 #[inline]
164 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165 Display::fmt(&self.inner.frame.err, f)
166 }
167}
168
169pub struct DetailedDisplay<'h, E> {
170 inner: &'h Err<E>
171}
172
173impl<'h, E> Display for DetailedDisplay<'h, E>
174where
175 E: ErrorTrait + Send + Sync + 'static
176{
177 #[inline]
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 print_err_dbg(
180 f,
181 (&*self.inner.frame).into(),
182 0,
183 &mut String::new()
184 )
185 }
186}
187
188pub struct ErrorImplementorBorrowed<'h, E> {
189 inner: &'h Err<E>
190}
191
192impl<'h, E> ErrorImplementorBorrowed<'h, E> {
193 #[inline]
194 pub fn as_err(&self) -> &Err<E> {
195 self.inner
196 }
197}
198
199impl<'h, E> Debug for ErrorImplementorBorrowed<'h, E>
200where
201 E: ErrorTrait + Send + Sync + 'static
202{
203 #[inline]
204 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
205 self.inner.detailed_display().fmt(f)
206 }
207}
208
209impl<'h, E> Display for ErrorImplementorBorrowed<'h, E>
210where
211 E: ErrorTrait + Send + Sync + 'static
212{
213 #[inline]
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 self.inner.simple_display().fmt(f)
216 }
217}
218
219impl<'h, E> ErrorTrait for ErrorImplementorBorrowed<'h, E>
220where
221 E: ErrorTrait + Send + Sync + 'static
222{}
223
224pub struct ErrorImplementorOwned<E> {
225 inner: Err<E>
226}
227
228impl<E> ErrorImplementorOwned<E> {
229 #[inline]
230 pub fn as_err(&self) -> &Err<E> {
231 &self.inner
232 }
233
234 #[inline]
235 pub fn into_err(self) -> Err<E> {
236 self.inner
237 }
238}
239
240impl<E> Debug for ErrorImplementorOwned<E>
241where
242 E: ErrorTrait + Send + Sync + 'static
243{
244 #[inline]
245 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246 self.inner.detailed_display().fmt(f)
247 }
248}
249
250impl<E> Display for ErrorImplementorOwned<E>
251where
252 E: ErrorTrait + Send + Sync + 'static
253{
254 #[inline]
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 self.inner.simple_display().fmt(f)
257 }
258}
259
260impl<E> ErrorTrait for ErrorImplementorOwned<E>
261where
262 E: ErrorTrait + Send + Sync + 'static
263{}
264
265struct StringError {
266 debug: Box<str>,
267 display: Box<str>
268}
269
270impl Debug for StringError {
271 #[inline]
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 f.write_str(&self.debug)
274 }
275}
276
277impl Display for StringError {
278 #[inline]
279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280 f.write_str(&self.display)
281 }
282}
283
284impl ErrorTrait for StringError {}
285
286#[track_caller]
287fn walk(err: &dyn ErrorTrait) -> Vec<Frame> {
288 if let Some(err) = err.source() {
289 vec![Frame {
290 err: Box::new(StringError {
291 debug: format!("{err:?}").into_boxed_str(),
292 display: format!("{err}").into_boxed_str()
293 }),
294 location: Location::caller(),
295 children: walk(err)
296 }]
297 } else {
298 Vec::new()
299 }
300}
301
302fn print_err_dbg(
303 f: &mut fmt::Formatter<'_>,
304 frame: BorrowedFrame<'_>,
305 level: usize,
306 prefix_buf: &mut String
307) -> fmt::Result {
308 let prefix_buf_len = prefix_buf.len();
309 let level_in_spaces = level * 2;
310 if prefix_buf_len < level_in_spaces {
311 let additional = level_in_spaces - prefix_buf_len;
312
313 prefix_buf.reserve(additional);
314 (0..additional).for_each(|_| prefix_buf.push(' '));
315 }
316 let prefix = &prefix_buf[..level_in_spaces];
317
318 write!(
319 f,
320 "{prefix}- err in {file}, at {line}:{col}",
321 file = frame.location.file(),
322 line = frame.location.line(),
323 col = frame.location.column()
324 )?;
325
326 write!(f, "\n{prefix} {}", frame.err)?;
327
328 if !frame.children.is_empty() {
329 write!(f, "\n{prefix} caused by:")?;
330 }
331
332 for child in frame.children {
333 writeln!(f)?;
334 print_err_dbg(f, child.into(), level + 1, prefix_buf)?;
335 }
336
337 Ok(())
338}
339
340pub trait ErrorExt {
341 fn raise(self) -> Err<Self>
342 where
343 Self: Sized;
344}
345
346impl<E> ErrorExt for E
347where
348 E: ErrorTrait + Send + Sync + 'static
349{
350 #[inline]
351 #[track_caller]
352 fn raise(self) -> Err<Self> {
353 Err::from_err(self)
354 }
355}
356
357pub trait OptionExt {
358 type Ok;
359
360 fn or_raise<E>(self, err: impl FnOnce() -> E) -> Result<Self::Ok, Err<E>>
361 where
362 E: ErrorTrait + Send + Sync + 'static;
363}
364
365impl<T> OptionExt for Option<T> {
366 type Ok = T;
367
368 #[inline]
369 #[track_caller]
370 fn or_raise<E>(self, err: impl FnOnce() -> E) -> Result<T, Err<E>>
371 where
372 E: ErrorTrait + Send + Sync + 'static
373 {
374 match self {
375 Some(value) => { Ok(value) }
376 None => { Err(Err::from_err(err())) }
377 }
378 }
379}
380
381pub trait ResultExt {
382 type Ok;
383 type Err;
384
385 fn or_raise<E>(self, err: impl FnOnce() -> E) -> Result<Self::Ok, Err<E>>
386 where
387 E: ErrorTrait + Send + Sync + 'static;
388}
389
390impl<T, E> ResultExt for Result<T, E>
391where
392 E: ErrorTrait + Send + Sync + 'static
393{
394 type Ok = T;
395 type Err = E;
396
397 #[inline]
398 #[track_caller]
399 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
400 where
401 E2: ErrorTrait + Send + Sync + 'static
402 {
403 match self {
404 Ok(value) => { Ok(value) }
405 Err(prev_err) => { Err(Err::from_err(prev_err).raise(err())) }
406 }
407 }
408}
409
410impl<T, E> ResultExt for Result<T, Err<E>>
411where
412 E: ErrorTrait + Send + Sync + 'static
413{
414 type Ok = T;
415 type Err = E;
416
417 #[inline]
418 #[track_caller]
419 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
420 where
421 E2: ErrorTrait + Send + Sync + 'static
422 {
423 match self {
424 Ok(value) => { Ok(value) }
425 Err(prev_err) => { Err(prev_err.raise(err())) }
426 }
427 }
428}
429
430pub trait ResultManyExt {
431 type Ok;
432 type Err;
433
434 fn or_raise<E>(self, err: impl FnOnce() -> E) -> Result<Self::Ok, Err<E>>
435 where
436 E: ErrorTrait + Send + Sync + 'static;
437}
438
439impl<T, E> ResultManyExt for Result<T, Vec<E>>
440where
441 E: ErrorTrait + Send + Sync + 'static
442{
443 type Ok = T;
444 type Err = E;
445
446 #[inline]
447 #[track_caller]
448 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
449 where
450 E2: ErrorTrait + Send + Sync + 'static
451 {
452 match self {
453 Ok(value) => { Ok(value) }
454 Err(errors) => { Err(Err::from_errs(err(), &mut errors.into_iter())) }
455 }
456 }
457}
458
459impl<T, E> ResultManyExt for Result<T, Vec<Err<E>>>
460where
461 E: ErrorTrait + Send + Sync + 'static
462{
463 type Ok = T;
464 type Err = E;
465
466 #[inline]
467 #[track_caller]
468 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
469 where
470 E2: ErrorTrait + Send + Sync + 'static
471 {
472 match self {
473 Ok(value) => { Ok(value) }
474 Err(errors) => {
475 let mut errors = errors
476 .into_iter()
477 .map(Err::into_error);
478
479 Err(Err::from_errs(err(), &mut errors))
480 }
481 }
482 }
483}
484
485impl<T, E> ResultManyExt for Result<T, &[E]>
486where
487 E: ErrorTrait + Clone + Send + Sync + 'static
488{
489 type Ok = T;
490 type Err = E;
491
492 #[inline]
493 #[track_caller]
494 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
495 where
496 E2: ErrorTrait + Send + Sync + 'static
497 {
498 match self {
499 Ok(value) => { Ok(value) }
500 Err(errors) => { Err(Err::from_errs(err(), &mut errors.iter().cloned())) }
501 }
502 }
503}
504
505impl<T, E, const N: usize> ResultManyExt for Result<T, [E; N]>
506where
507 E: ErrorTrait + Send + Sync + 'static
508{
509 type Ok = T;
510 type Err = E;
511
512 #[inline]
513 #[track_caller]
514 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
515 where
516 E2: ErrorTrait + Send + Sync + 'static
517 {
518 match self {
519 Ok(value) => { Ok(value) }
520 Err(errors) => { Err(Err::from_errs(err(), &mut errors.into_iter())) }
521 }
522 }
523}
524
525impl<T, E, const N: usize> ResultManyExt for Result<T, [Err<E>; N]>
526where
527 E: ErrorTrait + Send + Sync + 'static
528{
529 type Ok = T;
530 type Err = E;
531
532 #[inline]
533 #[track_caller]
534 fn or_raise<E2>(self, err: impl FnOnce() -> E2) -> Result<T, Err<E2>>
535 where
536 E2: ErrorTrait + Send + Sync + 'static
537 {
538 match self {
539 Ok(value) => { Ok(value) }
540 Err(errors) => {
541 let mut errors = errors
542 .into_iter()
543 .map(Err::into_error);
544
545 Err(Err::from_errs(err(), &mut errors))
546 }
547 }
548 }
549}
550
551#[doc(hidden)]
552pub mod __proc_macro_support {
553 pub use core::error::Error;
554 pub use core::fmt::{ Debug, Display };
555 pub use displaydoc::Display;
556}