1#[doc(hidden)]
8#[macro_export]
9macro_rules! assert_error_eq {
10 ($left:expr, $right:expr) => {
11 assert_eq!(
12 Into::<$crate::Error>::into($left).to_string(),
13 Into::<$crate::Error>::into($right).to_string(),
14 );
15 };
16 ($left:expr, $right:expr,) => {
17 $crate::assert_error_eq!($left, $right);
18 };
19 ($left:expr, $right:expr, $($arg:tt)+) => {
20 assert_eq!(
21 Into::<$crate::Error>::into($left).to_string(),
22 Into::<$crate::Error>::into($right).to_string(),
23 $($arg)+
24 );
25 }
26}
27
28#[doc(hidden)]
49#[macro_export]
50macro_rules! impl_error_conversion_with_kind {
51 ($source:ty, $kind:expr, $target:ty) => {
52 impl ::std::convert::From<$source> for $target {
53 fn from(error: $source) -> Self {
54 $kind.because(error)
55 }
56 }
57 };
58}
59
60#[doc(hidden)]
80#[macro_export]
81macro_rules! impl_error_conversion_with_adaptor {
82 ($source:ty, $adaptor:ty, $target:ty) => {
83 impl ::std::convert::From<$source> for $target {
84 fn from(error: $source) -> Self {
85 ::std::convert::Into::<$adaptor>::into(error).into()
86 }
87 }
88 };
89}
90
91#[doc(hidden)]
92#[macro_export]
93macro_rules! def_error_base_on_kind {
94 ($error:ident, $error_kind:ty, $comment_error:expr, $comment_because:expr, $comment_simple:expr) => {
95 #[doc = $comment_error]
96 #[derive(Error, Debug, Clone)]
97 pub struct $error {
98 kind: $error_kind,
99 inner: $crate::AnyError,
100 }
101
102 impl ::std::fmt::Display for $error {
103 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
104 if let Some(err) = self.cause() {
105 if f.alternate() {
106 write!(f, "{:?}: {:?}", self.kind(), err)
107 } else {
108 write!(f, "{:?}({:?})", self.kind(), err)
109 }
110 } else {
111 write!(f, "{:?}", self.kind())
112 }
113 }
114 }
115
116 impl ::std::convert::From<$error_kind> for $error {
117 fn from(kind: $error_kind) -> Self {
118 kind.because($crate::SilentError)
119 }
120 }
121
122 impl $error_kind {
123 #[doc = $comment_because]
124 pub fn because<E>(self, reason: E) -> $error
125 where
126 E: ::std::error::Error + Send + Sync + 'static,
127 {
128 $error {
129 kind: self,
130 inner: reason.into(),
131 }
132 }
133
134 #[doc = $comment_simple]
135 pub fn other<T>(self, reason: T) -> $error
136 where
137 T: ::std::fmt::Display,
138 {
139 $error {
140 kind: self,
141 inner: $crate::OtherError::new(reason.to_string()).into(),
142 }
143 }
144 }
145
146 impl $error {
147 pub fn kind(&self) -> $error_kind {
149 self.kind
150 }
151
152 pub fn downcast_ref<E>(&self) -> Option<&E>
154 where
155 E: ::std::fmt::Display + ::std::fmt::Debug + Send + Sync + 'static,
156 {
157 self.inner.downcast_ref::<E>()
158 }
159
160 pub fn root_cause(&self) -> &(dyn ::std::error::Error + 'static) {
162 self.inner.root_cause()
163 }
164
165 pub fn cause(&self) -> Option<&(dyn ::std::error::Error + 'static)> {
167 self.inner.chain().next()
168 }
169 }
170 };
171 ($error:ident, $error_kind:ty, $comment_error:expr) => {
172 def_error_base_on_kind!(
173 $error,
174 $error_kind,
175 $comment_error,
176 concat!(
177 "Creates `",
178 stringify!($error),
179 "` base on `",
180 stringify!($error_kind),
181 "` with an error as the reason."
182 ),
183 concat!(
184 "Creates `",
185 stringify!($error),
186 "` base on `",
187 stringify!($error_kind),
188 "` with a simple string as the reason."
189 )
190 );
191 };
192 ($error:ident, $error_kind:ty) => {
193 def_error_base_on_kind!($error, $error_kind, "/// TODO(doc): @witter");
194 };
195}