1use std::{any::Any, any::TypeId, error, fmt, sync::Arc};
2
3use crate::{Backtrace, Error, ErrorDiagnostic, ResultKind, ResultType, repr::ErrorRepr};
4
5#[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 tag(&self) -> Option<&crate::Bytes>;
23
24 fn service(&self) -> Option<&'static str>;
25
26 fn signature(&self) -> &'static str;
27
28 fn backtrace(&self) -> Option<&Backtrace>;
29
30 fn source(&self) -> Option<&(dyn error::Error + 'static)>;
31
32 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)>;
33}
34
35impl<E> ErrorInformation for ErrorRepr<E>
36where
37 E: ErrorDiagnostic,
38{
39 fn tp(&self) -> ResultType {
40 self.error.kind().tp()
41 }
42
43 fn tag(&self) -> Option<&crate::Bytes> {
44 ErrorDiagnostic::tag(self)
45 }
46
47 fn service(&self) -> Option<&'static str> {
48 ErrorDiagnostic::service(self)
49 }
50
51 fn signature(&self) -> &'static str {
52 self.error.kind().signature()
53 }
54
55 fn backtrace(&self) -> Option<&Backtrace> {
56 ErrorDiagnostic::backtrace(self)
57 }
58
59 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
60 self.error.source()
61 }
62
63 fn get_item(&self, id: &TypeId) -> Option<&(dyn Any + Send + Sync)> {
64 self.ext.map.get(id).map(AsRef::as_ref)
65 }
66}
67
68#[derive(Clone)]
72pub struct ErrorInfo {
73 inner: Arc<dyn ErrorInformation>,
74}
75
76impl ErrorInfo {
77 pub fn tp(&self) -> ResultType {
79 self.inner.tp()
80 }
81
82 pub fn tag(&self) -> Option<&crate::Bytes> {
84 self.inner.tag()
85 }
86
87 pub fn service(&self) -> Option<&'static str> {
89 self.inner.service()
90 }
91
92 pub fn signature(&self) -> &'static str {
94 self.inner.signature()
95 }
96
97 pub fn backtrace(&self) -> Option<&Backtrace> {
99 self.inner.backtrace()
100 }
101
102 pub fn get_item<T: 'static>(&self) -> Option<&T> {
104 self.inner
105 .get_item(&TypeId::of::<T>())
106 .and_then(|boxed| boxed.downcast_ref())
107 }
108}
109
110impl<E> From<Error<E>> for ErrorInfo
111where
112 E: ErrorDiagnostic,
113{
114 fn from(err: Error<E>) -> Self {
115 Self { inner: err.inner }
116 }
117}
118
119impl<E> From<&Error<E>> for ErrorInfo
120where
121 E: ErrorDiagnostic,
122{
123 fn from(err: &Error<E>) -> Self {
124 Self {
125 inner: err.inner.clone(),
126 }
127 }
128}
129
130impl error::Error for ErrorInfo {
131 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
132 self.inner.source()
133 }
134}
135
136impl fmt::Debug for ErrorInfo {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 fmt::Debug::fmt(&self.inner, f)
139 }
140}
141
142impl fmt::Display for ErrorInfo {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 fmt::Display::fmt(&self.inner, f)
145 }
146}
147
148impl ErrorDiagnostic for ErrorInfo {
149 type Kind = ErrorInfoType;
150
151 fn kind(&self) -> ErrorInfoType {
152 ErrorInfoType(self.tp(), self.inner.signature())
153 }
154
155 fn service(&self) -> Option<&'static str> {
156 self.inner.service()
157 }
158
159 fn backtrace(&self) -> Option<&Backtrace> {
160 self.inner.backtrace()
161 }
162}