1#[doc(hidden)]
3#[macro_export]
4macro_rules! impl_error_chain_processed {
5 (
7 types {}
8 $( $rest: tt )*
9 ) => {
10 impl_error_chain_processed! {
11 types {
12 Error, ErrorKind, ResultExt, Result;
13 }
14 $( $rest )*
15 }
16 };
17 (
19 types {
20 $error_name:ident, $error_kind_name:ident,
21 $result_ext_name:ident, $result_name:ident;
22 }
23 $( $rest: tt )*
24 ) => {
25 impl_error_chain_processed! {
26 types {
27 $error_name, $error_kind_name,
28 $result_ext_name;
29 }
30 $( $rest )*
31 }
32 #[allow(unused)]
34 pub type $result_name<T> = ::std::result::Result<T, $error_name>;
35 };
36 (
38 types {
39 $error_name:ident, $error_kind_name:ident,
40 $result_ext_name:ident;
41 }
42
43 links {
44 $( $link_variant:ident ( $link_error_path:path, $link_kind_path:path )
45 $( #[$meta_links:meta] )*; ) *
46 }
47
48 foreign_links {
49 $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
50 $( #[$meta_foreign_links:meta] )*; )*
51 }
52
53 errors {
54 $( $error_chunks:tt ) *
55 }
56
57 ) => {
58 #[derive(Debug)]
68 pub struct $error_name(
69 pub $error_kind_name,
72 #[doc(hidden)]
74 pub $crate::State,
75 );
76
77 impl $crate::ChainedError for $error_name {
78 type ErrorKind = $error_kind_name;
79
80 fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
81 $error_name(kind, state)
82 }
83
84 fn from_kind(kind: Self::ErrorKind) -> Self {
85 Self::from_kind(kind)
86 }
87
88 fn with_chain<E, K>(error: E, kind: K)
89 -> Self
90 where E: ::std::error::Error + Send + 'static,
91 K: Into<Self::ErrorKind>
92 {
93 Self::with_chain(error, kind)
94 }
95
96 fn kind(&self) -> &Self::ErrorKind {
97 self.kind()
98 }
99
100 fn iter(&self) -> $crate::Iter {
101 $crate::Iter::new(Some(self))
102 }
103
104 fn chain_err<F, EK>(self, error: F) -> Self
105 where F: FnOnce() -> EK,
106 EK: Into<$error_kind_name> {
107 self.chain_err(error)
108 }
109
110 fn backtrace(&self) -> Option<&$crate::Backtrace> {
111 self.backtrace()
112 }
113
114 impl_extract_backtrace!($error_name
115 $error_kind_name
116 $([$link_error_path, $(#[$meta_links])*])*);
117 }
118
119 #[allow(dead_code)]
120 impl $error_name {
121 pub fn from_kind(kind: $error_kind_name) -> $error_name {
123 $error_name(
124 kind,
125 $crate::State::default(),
126 )
127 }
128
129 pub fn with_chain<E, K>(error: E, kind: K)
131 -> $error_name
132 where E: ::std::error::Error + Send + 'static,
133 K: Into<$error_kind_name>
134 {
135 $error_name::with_boxed_chain(Box::new(error), kind)
136 }
137
138 pub fn with_boxed_chain<K>(error: Box<::std::error::Error + Send>, kind: K)
140 -> $error_name
141 where K: Into<$error_kind_name>
142 {
143 $error_name(
144 kind.into(),
145 $crate::State::new::<$error_name>(error, ),
146 )
147 }
148
149 pub fn kind(&self) -> &$error_kind_name {
151 &self.0
152 }
153
154 pub fn iter(&self) -> $crate::Iter {
156 $crate::ChainedError::iter(self)
157 }
158
159 pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
161 self.1.backtrace()
162 }
163
164 pub fn chain_err<F, EK>(self, error: F) -> $error_name
166 where F: FnOnce() -> EK, EK: Into<$error_kind_name> {
167 $error_name::with_chain(self, Self::from_kind(error().into()))
168 }
169
170 pub fn description(&self) -> &str {
173 self.0.description()
174 }
175 }
176
177 impl ::std::error::Error for $error_name {
178 fn description(&self) -> &str {
179 self.description()
180 }
181
182 #[allow(unknown_lints, renamed_and_removed_lints, unused_doc_comment, unused_doc_comments)]
183 fn cause(&self) -> Option<&::std::error::Error> {
184 match self.1.next_error {
185 Some(ref c) => Some(&**c),
186 None => {
187 match self.0 {
188 $(
189 $(#[$meta_foreign_links])*
190 $error_kind_name::$foreign_link_variant(ref foreign_err) => {
191 foreign_err.cause()
192 }
193 ) *
194 _ => None
195 }
196 }
197 }
198 }
199 }
200
201 impl ::std::fmt::Display for $error_name {
202 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
203 ::std::fmt::Display::fmt(&self.0, f)
204 }
205 }
206
207 $(
208 $(#[$meta_links])*
209 impl From<$link_error_path> for $error_name {
210 fn from(e: $link_error_path) -> Self {
211 $error_name(
212 $error_kind_name::$link_variant(e.0),
213 e.1,
214 )
215 }
216 }
217 ) *
218
219 $(
220 $(#[$meta_foreign_links])*
221 impl From<$foreign_link_error_path> for $error_name {
222 fn from(e: $foreign_link_error_path) -> Self {
223 $error_name::from_kind(
224 $error_kind_name::$foreign_link_variant(e)
225 )
226 }
227 }
228 ) *
229
230 impl From<$error_kind_name> for $error_name {
231 fn from(e: $error_kind_name) -> Self {
232 $error_name::from_kind(e)
233 }
234 }
235
236 impl<'a> From<&'a str> for $error_name {
237 fn from(s: &'a str) -> Self {
238 $error_name::from_kind(s.into())
239 }
240 }
241
242 impl From<String> for $error_name {
243 fn from(s: String) -> Self {
244 $error_name::from_kind(s.into())
245 }
246 }
247
248
249 impl_error_chain_kind! {
253 #[derive(Debug)]
255 pub enum $error_kind_name {
256
257 Msg(s: String) {
259 description(&s)
260 display("{}", s)
261 }
262
263 $(
264 $(#[$meta_links])*
265 $link_variant(e: $link_kind_path) {
266 description(e.description())
267 display("{}", e)
268 }
269 ) *
270
271 $(
272 $(#[$meta_foreign_links])*
273 $foreign_link_variant(err: $foreign_link_error_path) {
274 description(::std::error::Error::description(err))
275 display("{}", err)
276 }
277 ) *
278
279 $($error_chunks)*
280 }
281 }
282
283 $(
284 $(#[$meta_links])*
285 impl From<$link_kind_path> for $error_kind_name {
286 fn from(e: $link_kind_path) -> Self {
287 $error_kind_name::$link_variant(e)
288 }
289 }
290 ) *
291
292 impl<'a> From<&'a str> for $error_kind_name {
293 fn from(s: &'a str) -> Self {
294 $error_kind_name::Msg(s.to_string())
295 }
296 }
297
298 impl From<String> for $error_kind_name {
299 fn from(s: String) -> Self {
300 $error_kind_name::Msg(s)
301 }
302 }
303
304 impl From<$error_name> for $error_kind_name {
305 fn from(e: $error_name) -> Self {
306 e.0
307 }
308 }
309
310 pub trait $result_ext_name<T> {
314 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
319 where F: FnOnce() -> EK,
320 EK: Into<$error_kind_name>;
321 }
322
323 impl<T, E> $result_ext_name<T> for ::std::result::Result<T, E> where E: ::std::error::Error + Send + 'static {
324 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
325 where F: FnOnce() -> EK,
326 EK: Into<$error_kind_name> {
327 self.map_err(move |e| {
328 let state = $crate::State::new::<$error_name>(Box::new(e), );
329 $crate::ChainedError::new(callback().into(), state)
330 })
331 }
332 }
333
334 impl<T> $result_ext_name<T> for ::std::option::Option<T> {
335 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
336 where F: FnOnce() -> EK,
337 EK: Into<$error_kind_name> {
338 self.ok_or_else(move || {
339 $crate::ChainedError::from_kind(callback().into())
340 })
341 }
342 }
343
344
345 };
346}
347
348#[doc(hidden)]
350#[macro_export]
351macro_rules! error_chain_processing {
352 (
353 ({}, $b:tt, $c:tt, $d:tt)
354 types $content:tt
355 $( $tail:tt )*
356 ) => {
357 error_chain_processing! {
358 ($content, $b, $c, $d)
359 $($tail)*
360 }
361 };
362 (
363 ($a:tt, {}, $c:tt, $d:tt)
364 links $content:tt
365 $( $tail:tt )*
366 ) => {
367 error_chain_processing! {
368 ($a, $content, $c, $d)
369 $($tail)*
370 }
371 };
372 (
373 ($a:tt, $b:tt, {}, $d:tt)
374 foreign_links $content:tt
375 $( $tail:tt )*
376 ) => {
377 error_chain_processing! {
378 ($a, $b, $content, $d)
379 $($tail)*
380 }
381 };
382 (
383 ($a:tt, $b:tt, $c:tt, {})
384 errors $content:tt
385 $( $tail:tt )*
386 ) => {
387 error_chain_processing! {
388 ($a, $b, $c, $content)
389 $($tail)*
390 }
391 };
392 ( ($a:tt, $b:tt, $c:tt, $d:tt) ) => {
393 impl_error_chain_processed! {
394 types $a
395 links $b
396 foreign_links $c
397 errors $d
398 }
399 };
400}
401
402#[macro_export]
404macro_rules! error_chain {
405 ( $( $block_name:ident { $( $block_content:tt )* } )* ) => {
406 error_chain_processing! {
407 ({}, {}, {}, {})
408 $($block_name { $( $block_content )* })*
409 }
410 };
411}
412
413#[macro_export]
419#[doc(hidden)]
420macro_rules! impl_extract_backtrace {
421 ($error_name: ident
422 $error_kind_name: ident
423 $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
424 #[allow(unknown_lints, renamed_and_removed_lints, unused_doc_comment, unused_doc_comments)]
425 fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
426 -> Option<$crate::InternalBacktrace> {
427 if let Some(e) = e.downcast_ref::<$error_name>() {
428 return Some(e.1.backtrace.clone());
429 }
430 $(
431 $( #[$meta_links] )*
432 {
433 if let Some(e) = e.downcast_ref::<$link_error_path>() {
434 return Some(e.1.backtrace.clone());
435 }
436 }
437 ) *
438 None
439 }
440 }
441}