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