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 ErrorInfo {
54 pub fn tp(&self) -> ResultType {
55 self.inner.tp()
56 }
57
58 pub fn service(&self) -> Option<&'static str> {
59 self.inner.service()
60 }
61
62 pub fn signature(&self) -> &'static str {
63 self.inner.signature()
64 }
65
66 pub fn backtrace(&self) -> Option<&Backtrace> {
67 self.inner.backtrace()
68 }
69
70 pub fn get_item<T: 'static>(&self) -> Option<&T> {
71 self.inner
72 .get_item(&TypeId::of::<T>())
73 .and_then(|boxed| boxed.downcast_ref())
74 }
75}
76
77impl<E> From<Error<E>> for ErrorInfo
78where
79 E: ErrorDiagnostic,
80{
81 fn from(err: Error<E>) -> Self {
82 Self { inner: err.inner }
83 }
84}
85
86impl<E> From<&Error<E>> for ErrorInfo
87where
88 E: ErrorDiagnostic,
89{
90 fn from(err: &Error<E>) -> Self {
91 Self {
92 inner: err.inner.clone(),
93 }
94 }
95}
96
97impl error::Error for ErrorInfo {
98 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
99 self.inner.source()
100 }
101}
102
103impl fmt::Debug for ErrorInfo {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 fmt::Debug::fmt(&self.inner, f)
106 }
107}
108
109impl fmt::Display for ErrorInfo {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 fmt::Display::fmt(&self.inner, f)
112 }
113}
114
115#[derive(Copy, Clone, Debug, PartialEq, Eq)]
116pub struct ErrorInfoType(ResultType, &'static str);
117
118impl ResultKind for ErrorInfoType {
119 fn tp(&self) -> ResultType {
120 self.0
121 }
122
123 fn signature(&self) -> &'static str {
124 self.1
125 }
126}
127
128impl ErrorDiagnostic for ErrorInfo {
129 type Kind = ErrorInfoType;
130
131 fn kind(&self) -> ErrorInfoType {
132 ErrorInfoType(self.tp(), self.inner.signature())
133 }
134
135 fn service(&self) -> Option<&'static str> {
136 self.inner.service()
137 }
138
139 fn backtrace(&self) -> Option<&Backtrace> {
140 self.inner.backtrace()
141 }
142}