Skip to main content

ntex_error/
chain.rs

1use std::{error, fmt, panic::Location, sync::Arc};
2
3use crate::{Backtrace, Bytes, Error, ErrorDiagnostic, ResultKind, repr::ErrorRepr};
4
5/// A type-erased container representing an error within a diagnostic chain.
6///
7/// This allows errors to be stored and propagated without exposing concrete types.
8#[derive(Clone)]
9pub struct ErrorChain<K: ResultKind> {
10    error: Arc<dyn ErrorDiagnostic<Kind = K>>,
11}
12
13impl<K: ResultKind> ErrorChain<K> {
14    #[track_caller]
15    pub fn new<E>(error: E) -> Self
16    where
17        E: ErrorDiagnostic<Kind = K> + Sized,
18    {
19        Self {
20            error: Arc::new(ErrorRepr::new(error, None, Location::caller())),
21        }
22    }
23}
24
25impl<E, K> From<Error<E>> for ErrorChain<K>
26where
27    E: ErrorDiagnostic<Kind = K> + Sized,
28    K: ResultKind,
29{
30    fn from(err: Error<E>) -> Self {
31        Self { error: err.inner }
32    }
33}
34
35impl<K> error::Error for ErrorChain<K>
36where
37    K: ResultKind,
38{
39    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
40        self.error.source()
41    }
42}
43
44impl<K> fmt::Debug for ErrorChain<K>
45where
46    K: ResultKind,
47{
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        fmt::Debug::fmt(&self.error, f)
50    }
51}
52
53impl<K> fmt::Display for ErrorChain<K>
54where
55    K: ResultKind,
56{
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        fmt::Display::fmt(&self.error, f)
59    }
60}
61
62impl<K> ErrorDiagnostic for ErrorChain<K>
63where
64    K: ResultKind,
65{
66    type Kind = K;
67
68    fn kind(&self) -> Self::Kind {
69        self.error.kind()
70    }
71
72    fn tag(&self) -> Option<&Bytes> {
73        self.error.tag()
74    }
75
76    fn service(&self) -> Option<&'static str> {
77        self.error.service()
78    }
79
80    fn backtrace(&self) -> Option<&Backtrace> {
81        self.error.backtrace()
82    }
83}