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 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#[derive(Clone)]
66pub struct ErrorInfo {
67 inner: Arc<dyn ErrorInformation>,
68}
69
70impl ErrorInfo {
71 pub fn tp(&self) -> ResultType {
73 self.inner.tp()
74 }
75
76 pub fn service(&self) -> Option<&'static str> {
78 self.inner.service()
79 }
80
81 pub fn signature(&self) -> &'static str {
83 self.inner.signature()
84 }
85
86 pub fn backtrace(&self) -> Option<&Backtrace> {
88 self.inner.backtrace()
89 }
90
91 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}