Skip to main content

ntex_error/
info.rs

1use std::{any::Any, any::TypeId, error, fmt, sync::Arc};
2
3use crate::{Backtrace, Error, ErrorDiagnostic, ResultKind, ResultType, repr::ErrorRepr};
4
5/// Helper type holding a result type and classification signature.
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7pub struct ErrorInfoType(ResultType, &'static str);
8
9impl ResultKind for ErrorInfoType {
10    fn tp(&self) -> ResultType {
11        self.0
12    }
13
14    fn signature(&self) -> &'static str {
15        self.1
16    }
17}
18
19trait ErrorInformation: fmt::Display + fmt::Debug + 'static {
20    fn tp(&self) -> ResultType;
21
22    fn service(&self) -> Option<&'static str>;
23
24    fn signature(&self) -> &'static str;
25
26    fn backtrace(&self) -> Option<&Backtrace>;
27
28    fn source(&self) -> Option<&(dyn error::Error + 'static)>;
29
30    fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)>;
31}
32
33impl<E> ErrorInformation for ErrorRepr<E>
34where
35    E: ErrorDiagnostic,
36{
37    fn tp(&self) -> ResultType {
38        self.kind().tp()
39    }
40
41    fn service(&self) -> Option<&'static str> {
42        ErrorDiagnostic::service(self)
43    }
44
45    fn signature(&self) -> &'static str {
46        self.kind().signature()
47    }
48
49    fn backtrace(&self) -> Option<&Backtrace> {
50        ErrorDiagnostic::backtrace(self)
51    }
52
53    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
54        self.error.source()
55    }
56
57    fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)> {
58        self.ext.map.get(id).map(AsRef::as_ref)
59    }
60}
61
62/// Type-erased container holding error information.
63///
64/// This allows storing and passing error metadata without exposing the concrete type.
65#[derive(Clone)]
66pub struct ErrorInfo {
67    inner: Arc<dyn ErrorInformation>,
68}
69
70impl ErrorInfo {
71    /// Returns the classification of the result (e.g. success, client error, service error).
72    pub fn tp(&self) -> ResultType {
73        self.inner.tp()
74    }
75
76    /// Returns the name of the responsible service, if applicable.
77    pub fn service(&self) -> Option<&'static str> {
78        self.inner.service()
79    }
80
81    /// Returns a stable identifier for the specific error classification.
82    pub fn signature(&self) -> &'static str {
83        self.inner.signature()
84    }
85
86    /// Returns a backtrace for debugging purposes, if available.
87    pub fn backtrace(&self) -> Option<&Backtrace> {
88        self.inner.backtrace()
89    }
90
91    /// Returns a reference to a previously stored value of type `T` from this error.
92    pub fn get_item<T: 'static>(&self) -> Option<&T> {
93        self.inner
94            .get_item(&TypeId::of::<T>())
95            .and_then(|boxed| boxed.downcast_ref())
96    }
97}
98
99impl<E> From<Error<E>> for ErrorInfo
100where
101    E: ErrorDiagnostic,
102{
103    fn from(err: Error<E>) -> Self {
104        Self { inner: err.inner }
105    }
106}
107
108impl<E> From<&Error<E>> for ErrorInfo
109where
110    E: ErrorDiagnostic,
111{
112    fn from(err: &Error<E>) -> Self {
113        Self {
114            inner: err.inner.clone(),
115        }
116    }
117}
118
119impl error::Error for ErrorInfo {
120    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
121        self.inner.source()
122    }
123}
124
125impl fmt::Debug for ErrorInfo {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        fmt::Debug::fmt(&self.inner, f)
128    }
129}
130
131impl fmt::Display for ErrorInfo {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        fmt::Display::fmt(&self.inner, f)
134    }
135}
136
137impl ErrorDiagnostic for ErrorInfo {
138    type Kind = ErrorInfoType;
139
140    fn kind(&self) -> ErrorInfoType {
141        ErrorInfoType(self.tp(), self.inner.signature())
142    }
143
144    fn service(&self) -> Option<&'static str> {
145        self.inner.service()
146    }
147
148    fn backtrace(&self) -> Option<&Backtrace> {
149        self.inner.backtrace()
150    }
151}