1#[doc(hidden)]
2#[macro_export]
3#[cfg(not(has_error_source))]
4macro_rules! impl_error_chain_cause_or_source {
5 (
6 types {
7 $error_kind_name:ident
8 }
9
10 foreign_links {
11 $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
12 $( #[$meta_foreign_links:meta] )*; )*
13 }
14 ) => {
15 #[allow(unknown_lints, renamed_and_removed_lints)]
16 #[allow(unused_doc_comment, unused_doc_comments)]
17 fn cause(&self) -> Option<&::std::error::Error> {
18 match self.1.next_error {
19 Some(ref c) => Some(&**c),
20 None => {
21 match self.0 {
22 $(
23 $(#[$meta_foreign_links])*
24 $error_kind_name::$foreign_link_variant(ref foreign_err) => {
25 foreign_err.cause()
26 }
27 ) *
28 _ => None
29 }
30 }
31 }
32 }
33 };
34}
35
36#[cfg(has_error_source)]
37#[doc(hidden)]
38#[macro_export]
39macro_rules! impl_error_chain_cause_or_source {
40 (
41 types {
42 $error_kind_name:ident
43 }
44
45 foreign_links {
46 $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
47 $( #[$meta_foreign_links:meta] )*; )*
48 }
49 ) => {
50 #[allow(unknown_lints, renamed_and_removed_lints, bare_trait_objects)]
51 #[allow(unused_doc_comment, unused_doc_comments)]
52 fn source(&self) -> Option<&(std::error::Error + 'static)> {
53 match self.1.next_error {
54 Some(ref c) => Some(&**c),
55 None => {
56 match self.0 {
57 $(
58 $(#[$meta_foreign_links])*
59 $error_kind_name::$foreign_link_variant(ref foreign_err) => {
60 foreign_err.source()
61 }
62 ) *
63 _ => None
64 }
65 }
66 }
67 }
68 };
69}
70
71#[doc(hidden)]
73#[cfg(has_error_description_deprecated)]
74#[macro_export(local_inner_macros)]
75macro_rules! call_to_deprecated_description {
76 ($e:ident) => {
77 ""
78 };
79}
80
81#[doc(hidden)]
82#[cfg(not(has_error_description_deprecated))]
83#[macro_export(local_inner_macros)]
84macro_rules! call_to_deprecated_description {
85 ($e:ident) => {
86 ::std::error::Error::description($e)
87 };
88}
89
90#[doc(hidden)]
92#[macro_export(local_inner_macros)]
93macro_rules! impl_error_chain_processed {
94 (
96 types {}
97 $( $rest: tt )*
98 ) => {
99 impl_error_chain_processed! {
100 types {
101 Error, ErrorKind, ResultExt, Result;
102 }
103 $( $rest )*
104 }
105 };
106 (
108 types {
109 $error_name:ident, $error_kind_name:ident,
110 $result_ext_name:ident, $result_name:ident;
111 }
112 $( $rest: tt )*
113 ) => {
114 impl_error_chain_processed! {
115 types {
116 $error_name, $error_kind_name,
117 $result_ext_name;
118 }
119 $( $rest )*
120 }
121 #[allow(unused)]
123 pub type $result_name<T> = ::std::result::Result<T, $error_name>;
124 };
125
126 (
128 types {
129 $error_name:ident, $error_kind_name:ident, $($types:tt)*
130 }
131 links $links:tt
132 foreign_links $foreign_links:tt
133 errors { $($errors:tt)* }
134 ) => {
135 impl_error_chain_processed! {
136 types {
137 $error_name, $error_kind_name, $($types)*
138 }
139 skip_msg_variant
140 links $links
141 foreign_links $foreign_links
142 errors {
143 Msg(s: String) {
145 description(&s)
146 display("{}", s)
147 }
148
149 $($errors)*
150 }
151 }
152
153 impl<'a> From<&'a str> for $error_kind_name {
154 fn from(s: &'a str) -> Self {
155 $error_kind_name::Msg(s.into())
156 }
157 }
158
159 impl From<String> for $error_kind_name {
160 fn from(s: String) -> Self {
161 $error_kind_name::Msg(s)
162 }
163 }
164
165 impl<'a> From<&'a str> for $error_name {
166 fn from(s: &'a str) -> Self {
167 Self::from_kind(s.into())
168 }
169 }
170
171 impl From<String> for $error_name {
172 fn from(s: String) -> Self {
173 Self::from_kind(s.into())
174 }
175 }
176 };
177
178 (
180 types {
181 $error_name:ident, $error_kind_name:ident,
182 $result_ext_name:ident;
183 }
184
185 skip_msg_variant
186
187 links {
188 $( $link_variant:ident ( $link_error_path:path, $link_kind_path:path )
189 $( #[$meta_links:meta] )*; ) *
190 }
191
192 foreign_links {
193 $( $foreign_link_variant:ident ( $foreign_link_error_path:path )
194 $( #[$meta_foreign_links:meta] )*; )*
195 }
196
197 errors {
198 $( $error_chunks:tt ) *
199 }
200
201 ) => {
202 #[derive(Debug)]
212 pub struct $error_name(
213 pub $error_kind_name,
216 #[doc(hidden)]
218 pub $crate::State,
219 );
220
221 impl $crate::ChainedError for $error_name {
222 type ErrorKind = $error_kind_name;
223
224 fn new(kind: $error_kind_name, state: $crate::State) -> $error_name {
225 $error_name(kind, state)
226 }
227
228 fn from_kind(kind: Self::ErrorKind) -> Self {
229 Self::from_kind(kind)
230 }
231
232 fn with_chain<E, K>(error: E, kind: K)
233 -> Self
234 where E: ::std::error::Error + Send + 'static,
235 K: Into<Self::ErrorKind>
236 {
237 Self::with_chain(error, kind)
238 }
239
240 fn kind(&self) -> &Self::ErrorKind {
241 self.kind()
242 }
243
244 fn iter(&self) -> $crate::Iter {
245 $crate::Iter::new(Some(self))
246 }
247
248 fn chain_err<F, EK>(self, error: F) -> Self
249 where F: FnOnce() -> EK,
250 EK: Into<$error_kind_name> {
251 self.chain_err(error)
252 }
253
254 fn backtrace(&self) -> Option<&$crate::Backtrace> {
255 self.backtrace()
256 }
257
258 impl_extract_backtrace!($error_name
259 $error_kind_name
260 $([$link_error_path, $(#[$meta_links])*])*);
261 }
262
263 #[allow(dead_code)]
264 impl $error_name {
265 pub fn from_kind(kind: $error_kind_name) -> $error_name {
267 $error_name(
268 kind,
269 $crate::State::default(),
270 )
271 }
272
273 pub fn with_chain<E, K>(error: E, kind: K)
275 -> $error_name
276 where E: ::std::error::Error + Send + 'static,
277 K: Into<$error_kind_name>
278 {
279 $error_name::with_boxed_chain(Box::new(error), kind)
280 }
281
282 #[allow(unknown_lints, bare_trait_objects)]
284 pub fn with_boxed_chain<K>(error: Box<::std::error::Error + Send>, kind: K)
285 -> $error_name
286 where K: Into<$error_kind_name>
287 {
288 $error_name(
289 kind.into(),
290 $crate::State::new::<$error_name>(error, ),
291 )
292 }
293
294 pub fn kind(&self) -> &$error_kind_name {
296 &self.0
297 }
298
299 pub fn iter(&self) -> $crate::Iter {
301 $crate::ChainedError::iter(self)
302 }
303
304 pub fn backtrace(&self) -> Option<&$crate::Backtrace> {
306 self.1.backtrace()
307 }
308
309 pub fn chain_err<F, EK>(self, error: F) -> $error_name
311 where F: FnOnce() -> EK, EK: Into<$error_kind_name> {
312 $error_name::with_chain(self, Self::from_kind(error().into()))
313 }
314
315 pub fn description(&self) -> &str {
318 self.0.description()
319 }
320 }
321
322 impl ::std::error::Error for $error_name {
323 #[cfg(not(has_error_description_deprecated))]
324 fn description(&self) -> &str {
325 self.description()
326 }
327
328 impl_error_chain_cause_or_source!{
329 types {
330 $error_kind_name
331 }
332 foreign_links {
333 $( $foreign_link_variant ( $foreign_link_error_path )
334 $( #[$meta_foreign_links] )*; )*
335 }
336 }
337 }
338
339 impl ::std::fmt::Display for $error_name {
340 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
341 ::std::fmt::Display::fmt(&self.0, f)
342 }
343 }
344
345 $(
346 $(#[$meta_links])*
347 impl From<$link_error_path> for $error_name {
348 fn from(e: $link_error_path) -> Self {
349 $error_name(
350 $error_kind_name::$link_variant(e.0),
351 e.1,
352 )
353 }
354 }
355 ) *
356
357 $(
358 $(#[$meta_foreign_links])*
359 impl From<$foreign_link_error_path> for $error_name {
360 fn from(e: $foreign_link_error_path) -> Self {
361 $error_name::from_kind(
362 $error_kind_name::$foreign_link_variant(e)
363 )
364 }
365 }
366 ) *
367
368 impl From<$error_kind_name> for $error_name {
369 fn from(e: $error_kind_name) -> Self {
370 $error_name::from_kind(e)
371 }
372 }
373
374 impl_error_chain_kind! {
378 #[derive(Debug)]
380 pub enum $error_kind_name {
381 $(
382 $(#[$meta_links])*
383 $link_variant(e: $link_kind_path) {
384 description(e.description())
385 display("{}", e)
386 }
387 ) *
388
389 $(
390 $(#[$meta_foreign_links])*
391 $foreign_link_variant(err: $foreign_link_error_path) {
392 description(call_to_deprecated_description!(err))
393 display("{}", err)
394 }
395 ) *
396
397 $($error_chunks)*
398 }
399 }
400
401 $(
402 $(#[$meta_links])*
403 impl From<$link_kind_path> for $error_kind_name {
404 fn from(e: $link_kind_path) -> Self {
405 $error_kind_name::$link_variant(e)
406 }
407 }
408 ) *
409
410 impl From<$error_name> for $error_kind_name {
411 fn from(e: $error_name) -> Self {
412 e.0
413 }
414 }
415
416 pub trait $result_ext_name<T> {
420 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
425 where F: FnOnce() -> EK,
426 EK: Into<$error_kind_name>;
427 }
428
429 impl<T, E> $result_ext_name<T> for ::std::result::Result<T, E> where E: ::std::error::Error + Send + 'static {
430 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
431 where F: FnOnce() -> EK,
432 EK: Into<$error_kind_name> {
433 self.map_err(move |e| {
434 let state = $crate::State::new::<$error_name>(Box::new(e), );
435 $crate::ChainedError::new(callback().into(), state)
436 })
437 }
438 }
439
440 impl<T> $result_ext_name<T> for ::std::option::Option<T> {
441 fn chain_err<F, EK>(self, callback: F) -> ::std::result::Result<T, $error_name>
442 where F: FnOnce() -> EK,
443 EK: Into<$error_kind_name> {
444 self.ok_or_else(move || {
445 $crate::ChainedError::from_kind(callback().into())
446 })
447 }
448 }
449
450
451 };
452}
453
454#[doc(hidden)]
456#[macro_export(local_inner_macros)]
457macro_rules! error_chain_processing {
458 (
459 ({}, $($rest:tt)*)
460 types $content:tt
461 $( $tail:tt )*
462 ) => {
463 error_chain_processing! {
464 ($content, $($rest)*)
465 $($tail)*
466 }
467 };
468
469 (
470 ($a:tt, {}, $($rest:tt)*)
471 links $content:tt
472 $( $tail:tt )*
473 ) => {
474 error_chain_processing! {
475 ($a, $content, $($rest)*)
476 $($tail)*
477 }
478 };
479
480 (
481 ($a:tt, $b:tt, {}, $($rest:tt)*)
482 foreign_links $content:tt
483 $( $tail:tt )*
484 ) => {
485 error_chain_processing! {
486 ($a, $b, $content, $($rest)*)
487 $($tail)*
488 }
489 };
490
491 (
492 ($a:tt, $b:tt, $c:tt, {}, $($rest:tt)*)
493 errors $content:tt
494 $( $tail:tt )*
495 ) => {
496 error_chain_processing! {
497 ($a, $b, $c, $content, $($rest)*)
498 $($tail)*
499 }
500 };
501
502 (
503 ($a:tt, $b:tt, $c:tt, $d:tt, {}, $($rest:tt)*)
504 skip_msg_variant
505 $( $tail:tt )*
506 ) => {
507 error_chain_processing! {
508 ($a, $b, $c, $d, {skip_msg_variant}, $($rest)*)
509 $($tail)*
510 }
511 };
512
513 ( ($a:tt, $b:tt, $c:tt, $d:tt, {$($e:tt)*},) ) => {
514 impl_error_chain_processed! {
515 types $a
516 $($e)*
517 links $b
518 foreign_links $c
519 errors $d
520 }
521 };
522}
523
524#[macro_export(local_inner_macros)]
526macro_rules! error_chain {
527 ( $($args:tt)* ) => {
528 error_chain_processing! {
529 ({}, {}, {}, {}, {},)
530 $($args)*
531 }
532 };
533}
534
535#[macro_export]
541#[doc(hidden)]
542macro_rules! impl_extract_backtrace {
543 ($error_name: ident
544 $error_kind_name: ident
545 $([$link_error_path: path, $(#[$meta_links: meta])*])*) => {
546 #[allow(unknown_lints, renamed_and_removed_lints, bare_trait_objects)]
547 #[allow(unused_doc_comment, unused_doc_comments)]
548 fn extract_backtrace(e: &(::std::error::Error + Send + 'static))
549 -> Option<$crate::InternalBacktrace> {
550 if let Some(e) = e.downcast_ref::<$error_name>() {
551 return Some(e.1.backtrace.clone());
552 }
553 $(
554 $( #[$meta_links] )*
555 {
556 if let Some(e) = e.downcast_ref::<$link_error_path>() {
557 return Some(e.1.backtrace.clone());
558 }
559 }
560 ) *
561 None
562 }
563 }
564}