Coverage Report

Created: 2025-12-20 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/quick-error-2.0.1/src/lib.rs
Line
Count
Source
1
#![warn(missing_docs, rust_2018_idioms)]
2
//! A macro which makes errors easy to write
3
//!
4
//! Minimum type is like this:
5
//!
6
//! ```rust
7
//! #[macro_use] extern crate quick_error;
8
//! # fn main() {}
9
//!
10
//! quick_error! {
11
//!     #[derive(Debug)]
12
//!     pub enum SomeError {
13
//!         Variant1 {}
14
//!     }
15
//! }
16
//! ```
17
//! Both ``pub`` and non-public types may be declared, and all meta attributes
18
//! (such as ``#[derive(Debug)]``) are forwarded as is. The `Debug` must be
19
//! implemented (but you may do that yourself if you like). The documentation
20
//! comments ``/// something`` (as well as other meta attrbiutes) on variants
21
//! are allowed.
22
//!
23
//! # Allowed Syntax
24
//!
25
//! You may add arbitrary parameters to any struct variant:
26
//!
27
//! ```rust
28
//! # #[macro_use] extern crate quick_error;
29
//! # fn main() {}
30
//! #
31
//! quick_error! {
32
//!     #[derive(Debug)]
33
//!     pub enum SomeError {
34
//!         /// IO Error
35
//!         Io(err: std::io::Error) {}
36
//!         /// Utf8 Error
37
//!         Utf8(err: std::str::Utf8Error) {}
38
//!     }
39
//! }
40
//! ```
41
//!
42
//! Note unlike in normal Enum declarations you declare names of fields (which
43
//! are omitted from type). How they can be used is outlined below.
44
//!
45
//! Now you might have noticed trailing braces `{}`. They are used to define
46
//! implementations. By default:
47
//!
48
//! * `Error::source()` returns None (even if type wraps some value)
49
//! * `Display` outputs debug representation
50
//! * No `From` implementations are defined
51
//!
52
//! ```rust
53
//! # #[macro_use] extern crate quick_error;
54
//! # fn main() {}
55
//! #
56
//! quick_error! {
57
//!     #[derive(Debug)]
58
//!     pub enum SomeError {
59
//!         Io(err: std::io::Error) {
60
//!             display("{}", err)
61
//!         }
62
//!         Utf8(err: std::str::Utf8Error) {
63
//!             display("utf8 error")
64
//!         }
65
//!     }
66
//! }
67
//! ```
68
//!
69
//! To change `source` method to return some error, add `source(value)`, for
70
//! example:
71
//!
72
//! ```rust
73
//! # #[macro_use] extern crate quick_error;
74
//! # fn main() {}
75
//! #
76
//! quick_error! {
77
//!     #[derive(Debug)]
78
//!     pub enum SomeError {
79
//!         Io(err: std::io::Error) {
80
//!             source(err)
81
//!         }
82
//!         Utf8(err: std::str::Utf8Error) {
83
//!             display("utf8 error")
84
//!         }
85
//!         Other(err: Box<std::error::Error>) {
86
//!             source(&**err)
87
//!         }
88
//!     }
89
//! }
90
//! ```
91
//! Note you don't need to wrap value in `Some`, its implicit. In case you want
92
//! `None` returned just omit the `source`. You can't return `None`
93
//! conditionally.
94
//!
95
//! To change how each clause is `Display`ed add `display(pattern,..args)`,
96
//! for example:
97
//!
98
//! ```rust
99
//! # #[macro_use] extern crate quick_error;
100
//! # fn main() {}
101
//! #
102
//! quick_error! {
103
//!     #[derive(Debug)]
104
//!     pub enum SomeError {
105
//!         Io(err: std::io::Error) {
106
//!             display("I/O error: {}", err)
107
//!         }
108
//!         Utf8(err: std::str::Utf8Error) {
109
//!             display("Utf8 error, valid up to {}", err.valid_up_to())
110
//!         }
111
//!     }
112
//! }
113
//! ```
114
//!
115
//! If you need a reference to the error when `Display`ing, you can instead use
116
//! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference.
117
//!
118
//! ```rust
119
//! # #[macro_use] extern crate quick_error;
120
//! # fn main() {}
121
//! #
122
//! use std::error::Error; // put methods like `source()` of this trait into scope
123
//!
124
//! quick_error! {
125
//!     #[derive(Debug)]
126
//!     pub enum SomeError {
127
//!         Io(err: std::io::Error) {
128
//!             display(x) -> ("I/O: {}", err)
129
//!         }
130
//!         Utf8(err: std::str::Utf8Error) {
131
//!             display(self_) -> ("UTF-8 error. Valid up to {}", err.valid_up_to())
132
//!         }
133
//!     }
134
//! }
135
//! ```
136
//!
137
//! To convert to the type from any other, use one of the three forms of
138
//! `from` clause.
139
//!
140
//! For example, to convert simple wrapper use bare `from()`:
141
//!
142
//! ```rust
143
//! # #[macro_use] extern crate quick_error;
144
//! # fn main() {}
145
//! #
146
//! quick_error! {
147
//!     #[derive(Debug)]
148
//!     pub enum SomeError {
149
//!         Io(err: std::io::Error) {
150
//!             from()
151
//!         }
152
//!     }
153
//! }
154
//! ```
155
//!
156
//! This implements ``From<io::Error>``.
157
//!
158
//! To convert to singleton enumeration type (discarding the value), use
159
//! the `from(type)` form:
160
//!
161
//! ```rust
162
//! # #[macro_use] extern crate quick_error;
163
//! # fn main() {}
164
//! #
165
//! quick_error! {
166
//!     #[derive(Debug)]
167
//!     pub enum SomeError {
168
//!         FormatError {
169
//!             from(std::fmt::Error)
170
//!         }
171
//!     }
172
//! }
173
//! ```
174
//!
175
//! And the most powerful form is `from(var: type) -> (arguments...)`. It
176
//! might be used to convert to type with multiple arguments or for arbitrary
177
//! value conversions:
178
//!
179
//! ```rust
180
//! # #[macro_use] extern crate quick_error;
181
//! # fn main() {}
182
//! #
183
//! quick_error! {
184
//!     #[derive(Debug)]
185
//!     pub enum SomeError {
186
//!         FailedOperation(s: &'static str, errno: i32) {
187
//!             from(errno: i32) -> ("os error", errno)
188
//!             from(e: std::io::Error) -> ("io error", e.raw_os_error().unwrap())
189
//!         }
190
//!         /// Converts from both kinds of utf8 errors
191
//!         Utf8(err: std::str::Utf8Error) {
192
//!             from()
193
//!             from(err: std::string::FromUtf8Error) -> (err.utf8_error())
194
//!         }
195
//!     }
196
//! }
197
//! ```
198
//! # Context
199
//!
200
//! Since quick-error 1.1 we also have a `context` declaration, which is
201
//! similar to (the longest form of) `from`, but allows adding some context to
202
//! the error. We need a longer example to demonstrate this:
203
//!
204
//! ```rust
205
//! # #[macro_use] extern crate quick_error;
206
//! # use std::io;
207
//! # use std::fs::File;
208
//! # use std::path::{Path, PathBuf};
209
//! #
210
//! use quick_error::ResultExt;
211
//!
212
//! quick_error! {
213
//!     #[derive(Debug)]
214
//!     pub enum Error {
215
//!         File(filename: PathBuf, err: io::Error) {
216
//!             context(path: &'a Path, err: io::Error)
217
//!                 -> (path.to_path_buf(), err)
218
//!         }
219
//!     }
220
//! }
221
//!
222
//! fn openfile(path: &Path) -> Result<(), Error> {
223
//!     File::open(path).context(path)?;
224
//!
225
//!     // If we didn't have context, the line above would be written as;
226
//!     //
227
//!     // File::open(path)
228
//!     //     .map_err(|err| Error::File(path.to_path_buf(), err))?;
229
//!
230
//!     Ok(())
231
//! }
232
//!
233
//! # fn main() {
234
//! #     openfile(Path::new("/etc/somefile")).ok();
235
//! # }
236
//! ```
237
//!
238
//! Each `context(a: A, b: B)` clause implements
239
//! `From<Context<A, B>> for Error`. Which means multiple `context` clauses
240
//! are a subject to the normal coherence rules. Unfortunately, we can't
241
//! provide full support of generics for the context, but you may either use a
242
//! lifetime `'a` for references or `AsRef<Type>` (the latter means `A:
243
//! AsRef<Type>`, and `Type` must be concrete). It's also occasionally useful
244
//! to use a tuple as a type of the first argument.
245
//!
246
//! You also need to `use quick_error::ResultExt` extension trait to get
247
//! working `.context()` method.
248
//!
249
//! More info on context in [this article](http://bit.ly/1PsuxDt).
250
//!
251
//! All forms of `from`, `display`, `source`, and `context`
252
//! clauses can be combined and put in arbitrary order. Only `from` and
253
//! `context` can be used multiple times in single variant of enumeration.
254
//! Docstrings are also okay.  Empty braces can be omitted as of quick_error
255
//! 0.1.3.
256
//!
257
//! # Private Enums
258
//!
259
//! Since quick-error 1.2.0 we  have a way to make a private enum that is
260
//! wrapped by public structure:
261
//!
262
//! ```rust
263
//! #[macro_use] extern crate quick_error;
264
//! # fn main() {}
265
//!
266
//! quick_error! {
267
//!     #[derive(Debug)]
268
//!     pub enum PubError wraps ErrorEnum {
269
//!         Variant1 {}
270
//!     }
271
//! }
272
//! ```
273
//!
274
//! This generates data structures like this
275
//!
276
//! ```rust
277
//!
278
//! pub struct PubError(ErrorEnum);
279
//!
280
//! enum ErrorEnum {
281
//!     Variant1,
282
//! }
283
//!
284
//! ```
285
//!
286
//! Which in turn allows you to export just `PubError` in your crate and keep
287
//! actual enumeration private to the crate. This is useful to keep backwards
288
//! compatibility for error types. Currently there is no shorcuts to define
289
//! error constructors for the inner type, but we consider adding some in
290
//! future versions.
291
//!
292
//! It's possible to declare internal enum as public too.
293
//!
294
//!
295
296
/// Main macro that does all the work
297
#[macro_export]
298
macro_rules! quick_error {
299
300
    (   $(#[$meta:meta])*
301
        pub enum $name:ident { $($chunks:tt)* }
302
    ) => {
303
        quick_error!(SORT [pub enum $name $(#[$meta])* ]
304
            items [] buf []
305
            queue [ $($chunks)* ]);
306
    };
307
    (   $(#[$meta:meta])*
308
        enum $name:ident { $($chunks:tt)* }
309
    ) => {
310
        quick_error!(SORT [enum $name $(#[$meta])* ]
311
            items [] buf []
312
            queue [ $($chunks)* ]);
313
    };
314
315
    (   $(#[$meta:meta])*
316
        pub enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
317
    ) => {
318
        quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
319
        quick_error!(SORT [enum $enum_name $(#[$meta])* ]
320
            items [] buf []
321
            queue [ $($chunks)* ]);
322
    };
323
324
    (   $(#[$meta:meta])*
325
        pub enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
326
    ) => {
327
        quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
328
        quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
329
            items [] buf []
330
            queue [ $($chunks)* ]);
331
    };
332
    (   $(#[$meta:meta])*
333
        enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
334
    ) => {
335
        quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
336
        quick_error!(SORT [enum $enum_name $(#[$meta])* ]
337
            items [] buf []
338
            queue [ $($chunks)* ]);
339
    };
340
341
    (   $(#[$meta:meta])*
342
        enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
343
    ) => {
344
        quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
345
        quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
346
            items [] buf []
347
            queue [ $($chunks)* ]);
348
    };
349
350
351
    (
352
        WRAPPER $internal:ident [ $($strdef:tt)* ] $strname:ident
353
        $(#[$meta:meta])*
354
    ) => {
355
        $(#[$meta])*
356
        $($strdef)* $strname ( $internal );
357
358
        impl ::std::fmt::Display for $strname {
359
            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>)
360
                -> ::std::fmt::Result
361
            {
362
                ::std::fmt::Display::fmt(&self.0, f)
363
            }
364
        }
365
366
        impl From<$internal> for $strname {
367
            fn from(err: $internal) -> Self {
368
                $strname(err)
369
            }
370
        }
371
372
        impl ::std::error::Error for $strname {
373
            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
374
                self.0.source()
375
            }
376
        }
377
    };
378
379
    // Queue is empty, can do the work
380
    (SORT [enum $name:ident $( #[$meta:meta] )*]
381
        items [$($( #[$imeta:meta] )*
382
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
383
                                {$( $ifuncs:tt )*} )* ]
384
        buf [ ]
385
        queue [ ]
386
    ) => {
387
        quick_error!(ENUM_DEFINITION [enum $name $( #[$meta] )*]
388
            body []
389
            queue [$($( #[$imeta] )*
390
                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
391
        );
392
        quick_error!(IMPLEMENTATIONS $name {$(
393
           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
394
           )*});
395
        $(
396
            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
397
        )*
398
    };
399
    (SORT [pub enum $name:ident $( #[$meta:meta] )*]
400
        items [$($( #[$imeta:meta] )*
401
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
402
                                {$( $ifuncs:tt )*} )* ]
403
        buf [ ]
404
        queue [ ]
405
    ) => {
406
        quick_error!(ENUM_DEFINITION [pub enum $name $( #[$meta] )*]
407
            body []
408
            queue [$($( #[$imeta] )*
409
                      => $iitem: $imode [$( $ivar: $ityp ),*] )*]
410
        );
411
        quick_error!(IMPLEMENTATIONS $name {$(
412
           $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
413
           )*});
414
        $(
415
            quick_error!(ERROR_CHECK $imode $($ifuncs)*);
416
        )*
417
    };
418
    // Add meta to buffer
419
    (SORT [$( $def:tt )*]
420
        items [$($( #[$imeta:meta] )*
421
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
422
                                {$( $ifuncs:tt )*} )* ]
423
        buf [$( #[$bmeta:meta] )*]
424
        queue [ #[$qmeta:meta] $( $tail:tt )*]
425
    ) => {
426
        quick_error!(SORT [$( $def )*]
427
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
428
            buf [$( #[$bmeta] )* #[$qmeta] ]
429
            queue [$( $tail )*]);
430
    };
431
    // Add ident to buffer
432
    (SORT [$( $def:tt )*]
433
        items [$($( #[$imeta:meta] )*
434
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
435
                                {$( $ifuncs:tt )*} )* ]
436
        buf [$( #[$bmeta:meta] )*]
437
        queue [ $qitem:ident $( $tail:tt )*]
438
    ) => {
439
        quick_error!(SORT [$( $def )*]
440
            items [$( $(#[$imeta])*
441
                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
442
            buf [$(#[$bmeta])* => $qitem : UNIT [ ] ]
443
            queue [$( $tail )*]);
444
    };
445
    // Flush buffer on meta after ident
446
    (SORT [$( $def:tt )*]
447
        items [$($( #[$imeta:meta] )*
448
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
449
                                {$( $ifuncs:tt )*} )* ]
450
        buf [$( #[$bmeta:meta] )*
451
            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
452
        queue [ #[$qmeta:meta] $( $tail:tt )*]
453
    ) => {
454
        quick_error!(SORT [$( $def )*]
455
            items [$($( #[$imeta:meta] )*
456
                      => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
457
                     $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
458
            buf [ #[$qmeta] ]
459
            queue [$( $tail )*]);
460
    };
461
    // Add tuple enum-variant
462
    (SORT [$( $def:tt )*]
463
        items [$($( #[$imeta:meta] )*
464
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
465
                                {$( $ifuncs:tt )*} )* ]
466
        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
467
        queue [($( $qvar:ident: $qtyp:ty ),+) $( $tail:tt )*]
468
    ) => {
469
        quick_error!(SORT [$( $def )*]
470
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
471
            buf [$( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),+] ]
472
            queue [$( $tail )*]
473
        );
474
    };
475
    // Add struct enum-variant - e.g. { descr: &'static str }
476
    (SORT [$( $def:tt )*]
477
        items [$($( #[$imeta:meta] )*
478
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
479
                                {$( $ifuncs:tt )*} )* ]
480
        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
481
        queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*]
482
    ) => {
483
        quick_error!(SORT [$( $def )*]
484
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
485
            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
486
            queue [$( $tail )*]);
487
    };
488
    // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
489
    (SORT [$( $def:tt )*]
490
        items [$($( #[$imeta:meta] )*
491
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
492
                                {$( $ifuncs:tt )*} )* ]
493
        buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
494
        queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*]
495
    ) => {
496
        quick_error!(SORT [$( $def )*]
497
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
498
            buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),+] ]
499
            queue [$( $tail )*]);
500
    };
501
    // Add braces and flush always on braces
502
    (SORT [$( $def:tt )*]
503
        items [$($( #[$imeta:meta] )*
504
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
505
                                {$( $ifuncs:tt )*} )* ]
506
        buf [$( #[$bmeta:meta] )*
507
                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
508
        queue [ {$( $qfuncs:tt )*} $( $tail:tt )*]
509
    ) => {
510
        quick_error!(SORT [$( $def )*]
511
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
512
                      $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ]
513
            buf [ ]
514
            queue [$( $tail )*]);
515
    };
516
    // Flush buffer on double ident
517
    (SORT [$( $def:tt )*]
518
        items [$($( #[$imeta:meta] )*
519
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
520
                                {$( $ifuncs:tt )*} )* ]
521
        buf [$( #[$bmeta:meta] )*
522
                 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
523
        queue [ $qitem:ident $( $tail:tt )*]
524
    ) => {
525
        quick_error!(SORT [$( $def )*]
526
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
527
                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
528
            buf [ => $qitem : UNIT [ ] ]
529
            queue [$( $tail )*]);
530
    };
531
    // Flush buffer on end
532
    (SORT [$( $def:tt )*]
533
        items [$($( #[$imeta:meta] )*
534
                  => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
535
                                {$( $ifuncs:tt )*} )* ]
536
        buf [$( #[$bmeta:meta] )*
537
            => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
538
        queue [ ]
539
    ) => {
540
        quick_error!(SORT [$( $def )*]
541
            items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
542
                     $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
543
            buf [ ]
544
            queue [ ]);
545
    };
546
    // Public enum (Queue Empty)
547
    (ENUM_DEFINITION [pub enum $name:ident $( #[$meta:meta] )*]
548
        body [$($( #[$imeta:meta] )*
549
            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
550
        queue [ ]
551
    ) => {
552
        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
553
        #[allow(renamed_and_removed_lints)]
554
        #[allow(unused_doc_comment)]
555
        #[allow(unused_doc_comments)]
556
        $(#[$meta])*
557
        pub enum $name {
558
            $(
559
                $(#[$imeta])*
560
                $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*,
561
            )*
562
        }
563
    };
564
    // Private enum (Queue Empty)
565
    (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*]
566
        body [$($( #[$imeta:meta] )*
567
            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
568
        queue [ ]
569
    ) => {
570
        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
571
        #[allow(renamed_and_removed_lints)]
572
        #[allow(unused_doc_comment)]
573
        #[allow(unused_doc_comments)]
574
        $(#[$meta])*
575
        enum $name {
576
            $(
577
                $(#[$imeta])*
578
                $iitem $(($( $ttyp ),+))* $({$( $svar: $styp ),*})*,
579
            )*
580
        }
581
    };
582
    // Unit variant
583
    (ENUM_DEFINITION [$( $def:tt )*]
584
        body [$($( #[$imeta:meta] )*
585
            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
586
        queue [$( #[$qmeta:meta] )*
587
            => $qitem:ident: UNIT [ ] $( $queue:tt )*]
588
    ) => {
589
        quick_error!(ENUM_DEFINITION [ $($def)* ]
590
            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
591
                    $( #[$qmeta] )* => $qitem () {} ]
592
            queue [ $($queue)* ]
593
        );
594
    };
595
    // Tuple variant
596
    (ENUM_DEFINITION [$( $def:tt )*]
597
        body [$($( #[$imeta:meta] )*
598
            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
599
        queue [$( #[$qmeta:meta] )*
600
            => $qitem:ident: TUPLE [$( $qvar:ident: $qtyp:ty ),+] $( $queue:tt )*]
601
    ) => {
602
        quick_error!(ENUM_DEFINITION [ $($def)* ]
603
            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
604
                    $( #[$qmeta] )* => $qitem (($( $qtyp ),+)) {} ]
605
            queue [ $($queue)* ]
606
        );
607
    };
608
    // Struct variant
609
    (ENUM_DEFINITION [$( $def:tt )*]
610
        body [$($( #[$imeta:meta] )*
611
            => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
612
        queue [$( #[$qmeta:meta] )*
613
            => $qitem:ident: STRUCT [$( $qvar:ident: $qtyp:ty ),*] $( $queue:tt )*]
614
    ) => {
615
        quick_error!(ENUM_DEFINITION [ $($def)* ]
616
            body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
617
                    $( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ]
618
            queue [ $($queue)* ]
619
        );
620
    };
621
    (IMPLEMENTATIONS
622
        $name:ident {$(
623
            $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
624
        )*}
625
    ) => {
626
        #[allow(unused_variables)]
627
        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
628
        #[allow(renamed_and_removed_lints)]
629
        #[allow(unused_doc_comment)]
630
        #[allow(unused_doc_comments)]
631
        impl ::std::fmt::Display for $name {
632
124
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
633
124
                -> ::std::fmt::Result
634
            {
635
124
                match *self {
636
                    $(
637
                        $(#[$imeta])*
638
6
                        quick_error!(ITEM_PATTERN
639
                            $name $item: $imode [$( ref $var ),*]
640
                        ) => {
641
6
                            let display_fn = quick_error!(FIND_DISPLAY_IMPL
642
                                $name $item: $imode
643
                                {$( $funcs )*});
644
645
6
                            display_fn(self, fmt)
646
                        }
647
                    )*
648
                }
649
124
            }
Unexecuted instantiation: <image_webp::encoder::EncodingError as core::fmt::Display>::fmt
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt
Line
Count
Source
632
124
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
633
124
                -> ::std::fmt::Result
634
            {
635
124
                match *self {
636
                    $(
637
                        $(#[$imeta])*
638
6
                        quick_error!(ITEM_PATTERN
639
                            $name $item: $imode [$( ref $var ),*]
640
                        ) => {
641
6
                            let display_fn = quick_error!(FIND_DISPLAY_IMPL
642
                                $name $item: $imode
643
                                {$( $funcs )*});
644
645
6
                            display_fn(self, fmt)
646
                        }
647
                    )*
648
                }
649
124
            }
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt
Unexecuted instantiation: <ravif::error::Error as core::fmt::Display>::fmt
650
        }
651
        #[allow(unused_variables)]
652
        #[allow(unknown_lints)]  // no unused_doc_comments in older rust
653
        #[allow(renamed_and_removed_lints)]
654
        #[allow(unused_doc_comment)]
655
        #[allow(unused_doc_comments)]
656
        impl ::std::error::Error for $name {
657
0
            fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
658
0
                match *self {
659
                    $(
660
                        $(#[$imeta])*
661
0
                        quick_error!(ITEM_PATTERN
662
                            $name $item: $imode [$( ref $var ),*]
663
                        ) => {
664
0
                            quick_error!(FIND_SOURCE_IMPL
665
                                $item: $imode [$( $var ),*]
666
                                {$( $funcs )*})
667
                        }
668
                    )*
669
                }
670
0
            }
Unexecuted instantiation: <image_webp::encoder::EncodingError as core::error::Error>::source
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::error::Error>::source
Unexecuted instantiation: <tiff::error::TiffError as core::error::Error>::source
Unexecuted instantiation: <tiff::error::TiffFormatError as core::error::Error>::source
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::error::Error>::source
Unexecuted instantiation: <tiff::error::UsageError as core::error::Error>::source
Unexecuted instantiation: <ravif::error::Error as core::error::Error>::source
671
        }
672
        $(
673
            quick_error!(FIND_FROM_IMPL
674
                $name $item: $imode [$( $var:$typ ),*]
675
                {$( $funcs )*});
676
        )*
677
        $(
678
            quick_error!(FIND_CONTEXT_IMPL
679
                $name $item: $imode [$( $var:$typ ),*]
680
                {$( $funcs )*});
681
        )*
682
    };
683
    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
684
        { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
685
    ) => {
686
        |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $( $exprs )*) }
687
    };
688
    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
689
        { display($pattern:expr) $( $tail:tt )*}
690
    ) => {
691
124
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <image_webp::encoder::EncodingError as core::fmt::Display>::fmt::{closure#1}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#2}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#3}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#4}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#5}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#6}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#7}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#8}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#9}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#10}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#11}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#1}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#12}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#13}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#14}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#15}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#16}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#17}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#18}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#19}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#20}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#21}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#22}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#23}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#24}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#25}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#26}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#27}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#28}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#2}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#3}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#4}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#5}
Unexecuted instantiation: <tiff::error::TiffError as core::fmt::Display>::fmt::{closure#1}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#2}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#3}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#4}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#5}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#6}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#7}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#8}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#9}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#10}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#11}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#1}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#12}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#13}
Unexecuted instantiation: <tiff::error::TiffFormatError as core::fmt::Display>::fmt::{closure#14}
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#0}
Line
Count
Source
691
6
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#2}
Line
Count
Source
691
9
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#3}
Line
Count
Source
691
10
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#4}
Line
Count
Source
691
7
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#5}
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#6}
Line
Count
Source
691
12
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#7}
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#8}
Line
Count
Source
691
77
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#9}
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#10}
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#11}
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#1}
Line
Count
Source
691
2
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#12}
Unexecuted instantiation: <tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#13}
<tiff::error::TiffUnsupportedError as core::fmt::Display>::fmt::{closure#14}
Line
Count
Source
691
1
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern) }
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#2}
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#3}
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#4}
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#5}
Unexecuted instantiation: <tiff::error::UsageError as core::fmt::Display>::fmt::{closure#1}
Unexecuted instantiation: <ravif::error::Error as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <ravif::error::Error as core::fmt::Display>::fmt::{closure#2}
692
    };
693
    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
694
        { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
695
    ) => {
696
0
        |_, f: &mut ::std::fmt::Formatter<'_>| { write!(f, $pattern, $( $exprs )*) }
Unexecuted instantiation: <image_webp::encoder::EncodingError as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <image_webp::decoder::DecodingError as core::fmt::Display>::fmt::{closure#0}
Unexecuted instantiation: <ravif::error::Error as core::fmt::Display>::fmt::{closure#1}
697
    };
698
    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
699
        { $t:tt $( $tail:tt )*}
700
    ) => {
701
        quick_error!(FIND_DISPLAY_IMPL
702
            $name $item: $imode
703
            {$( $tail )*})
704
    };
705
    (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
706
        { }
707
    ) => {
708
        |self_: &$name, f: &mut ::std::fmt::Formatter<'_>| {
709
            write!(f, "{:?}", self_)
710
        }
711
    };
712
    (FIND_SOURCE_IMPL $item:ident: $imode:tt
713
        [$( $var:ident ),*]
714
        { source($expr:expr) $( $tail:tt )*}
715
    ) => {
716
        Some($expr)
717
    };
718
    (FIND_SOURCE_IMPL $item:ident: $imode:tt
719
        [$( $var:ident ),*]
720
        { $t:tt $( $tail:tt )*}
721
    ) => {
722
        quick_error!(FIND_SOURCE_IMPL
723
            $item: $imode [$( $var ),*]
724
            { $($tail)* })
725
    };
726
    (FIND_SOURCE_IMPL $item:ident: $imode:tt
727
        [$( $var:ident ),*]
728
        { }
729
    ) => {
730
        None
731
    };
732
    // ----------------------------- FROM IMPL --------------------------
733
    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
734
        [$( $var:ident: $typ:ty ),*]
735
        { from() $( $tail:tt )*}
736
    ) => {
737
        $(
738
            impl From<$typ> for $name {
739
5.13k
                fn from($var: $typ) -> $name {
740
5.13k
                    $name::$item($var)
741
5.13k
                }
Unexecuted instantiation: <image_webp::encoder::EncodingError as core::convert::From<std::io::error::Error>>::from
<image_webp::decoder::DecodingError as core::convert::From<std::io::error::Error>>::from
Line
Count
Source
739
766
                fn from($var: $typ) -> $name {
740
766
                    $name::$item($var)
741
766
                }
<tiff::error::TiffError as core::convert::From<tiff::error::TiffFormatError>>::from
Line
Count
Source
739
183
                fn from($var: $typ) -> $name {
740
183
                    $name::$item($var)
741
183
                }
<tiff::error::TiffError as core::convert::From<tiff::error::TiffUnsupportedError>>::from
Line
Count
Source
739
93
                fn from($var: $typ) -> $name {
740
93
                    $name::$item($var)
741
93
                }
<tiff::error::TiffError as core::convert::From<std::io::error::Error>>::from
Line
Count
Source
739
4.09k
                fn from($var: $typ) -> $name {
740
4.09k
                    $name::$item($var)
741
4.09k
                }
Unexecuted instantiation: <tiff::error::TiffError as core::convert::From<tiff::error::UsageError>>::from
742
            }
743
        )*
744
        quick_error!(FIND_FROM_IMPL
745
            $name $item: $imode [$( $var:$typ ),*]
746
            {$( $tail )*});
747
    };
748
    (FIND_FROM_IMPL $name:ident $item:ident: UNIT
749
        [ ]
750
        { from($ftyp:ty) $( $tail:tt )*}
751
    ) => {
752
        impl From<$ftyp> for $name {
753
            fn from(_discarded_error: $ftyp) -> $name {
754
                $name::$item
755
            }
756
        }
757
        quick_error!(FIND_FROM_IMPL
758
            $name $item: UNIT [  ]
759
            {$( $tail )*});
760
    };
761
    (FIND_FROM_IMPL $name:ident $item:ident: TUPLE
762
        [$( $var:ident: $typ:ty ),*]
763
        { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
764
    ) => {
765
        impl From<$ftyp> for $name {
766
0
            fn from($fvar: $ftyp) -> $name {
767
0
                $name::$item($( $texpr ),*)
768
0
            }
Unexecuted instantiation: <ravif::error::Error as core::convert::From<rav1e::api::config::InvalidConfig>>::from
Unexecuted instantiation: <ravif::error::Error as core::convert::From<rav1e::api::util::EncoderStatus>>::from
769
        }
770
        quick_error!(FIND_FROM_IMPL
771
            $name $item: TUPLE [$( $var:$typ ),*]
772
            { $($tail)* });
773
    };
774
    (FIND_FROM_IMPL $name:ident $item:ident: STRUCT
775
        [$( $var:ident: $typ:ty ),*]
776
        { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
777
    ) => {
778
        impl From<$ftyp> for $name {
779
            fn from($fvar: $ftyp) -> $name {
780
                $name::$item {
781
                    $( $tvar: $texpr ),*
782
                }
783
            }
784
        }
785
        quick_error!(FIND_FROM_IMPL
786
            $name $item: STRUCT [$( $var:$typ ),*]
787
            { $($tail)* });
788
    };
789
    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
790
        [$( $var:ident: $typ:ty ),*]
791
        { $t:tt $( $tail:tt )*}
792
    ) => {
793
        quick_error!(FIND_FROM_IMPL
794
            $name $item: $imode [$( $var:$typ ),*]
795
            {$( $tail )*}
796
        );
797
    };
798
    (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
799
        [$( $var:ident: $typ:ty ),*]
800
        { }
801
    ) => {
802
    };
803
    // ----------------------------- CONTEXT IMPL --------------------------
804
    (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
805
        [$( $var:ident: $typ:ty ),*]
806
        { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
807
            -> ($( $texpr:expr ),*) $( $tail:tt )* }
808
    ) => {
809
        impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
810
            fn from(
811
                $crate::Context($cvar, $fvar): $crate::Context<T, $ftyp>)
812
                -> $name
813
            {
814
                $name::$item($( $texpr ),*)
815
            }
816
        }
817
        quick_error!(FIND_CONTEXT_IMPL
818
            $name $item: TUPLE [$( $var:$typ ),*]
819
            { $($tail)* });
820
    };
821
    (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
822
        [$( $var:ident: $typ:ty ),*]
823
        { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
824
            -> ($( $texpr:expr ),*) $( $tail:tt )* }
825
    ) => {
826
        impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
827
            fn from(
828
                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
829
                -> $name
830
            {
831
                $name::$item($( $texpr ),*)
832
            }
833
        }
834
        quick_error!(FIND_CONTEXT_IMPL
835
            $name $item: TUPLE [$( $var:$typ ),*]
836
            { $($tail)* });
837
    };
838
    (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
839
        [$( $var:ident: $typ:ty ),*]
840
        { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
841
            -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
842
    ) => {
843
        impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
844
            fn from(
845
                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
846
                -> $name
847
            {
848
                $name::$item {
849
                    $( $tvar: $texpr ),*
850
                }
851
            }
852
        }
853
        quick_error!(FIND_CONTEXT_IMPL
854
            $name $item: STRUCT [$( $var:$typ ),*]
855
            { $($tail)* });
856
    };
857
    (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
858
        [$( $var:ident: $typ:ty ),*]
859
        { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
860
            -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
861
    ) => {
862
        impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
863
            fn from(
864
                $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
865
                -> $name
866
            {
867
                $name::$item {
868
                    $( $tvar: $texpr ),*
869
                }
870
            }
871
        }
872
        quick_error!(FIND_CONTEXT_IMPL
873
            $name $item: STRUCT [$( $var:$typ ),*]
874
            { $($tail)* });
875
    };
876
    (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
877
        [$( $var:ident: $typ:ty ),*]
878
        { $t:tt $( $tail:tt )*}
879
    ) => {
880
        quick_error!(FIND_CONTEXT_IMPL
881
            $name $item: $imode [$( $var:$typ ),*]
882
            {$( $tail )*}
883
        );
884
    };
885
    (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
886
        [$( $var:ident: $typ:ty ),*]
887
        { }
888
    ) => {
889
    };
890
    // ----------------------------- ITEM IMPL --------------------------
891
    (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
892
    ) => { };
893
    (ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE
894
        [$( $typ:ty ),*]
895
    ) => {
896
        ($( $typ ),*)
897
    };
898
    (ITEM_BODY $(#[$imeta:meta])* $item:ident: STRUCT
899
        [$( $var:ident: $typ:ty ),*]
900
    ) => {
901
        {$( $var:$typ ),*}
902
    };
903
    (ITEM_PATTERN $name:ident $item:ident: UNIT []
904
    ) => {
905
        $name::$item
906
    };
907
    (ITEM_PATTERN $name:ident $item:ident: TUPLE
908
        [$( ref $var:ident ),*]
909
    ) => {
910
        $name::$item ($( ref $var ),*)
911
    };
912
    (ITEM_PATTERN $name:ident $item:ident: STRUCT
913
        [$( ref $var:ident ),*]
914
    ) => {
915
        $name::$item {$( ref $var ),*}
916
    };
917
    // This one should match all allowed sequences in "funcs" but not match
918
    // anything else.
919
    // This is to contrast FIND_* clauses which just find stuff they need and
920
    // skip everything else completely
921
    (ERROR_CHECK $imode:tt display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*)
922
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
923
    (ERROR_CHECK $imode:tt display($pattern: expr) $( $tail:tt )*)
924
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
925
    (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*)
926
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
927
    (ERROR_CHECK $imode:tt source($expr:expr) $($tail:tt)*)
928
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
929
    (ERROR_CHECK $imode:tt from() $($tail:tt)*)
930
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
931
    (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*)
932
    => { quick_error!(ERROR_CHECK $imode $($tail)*); };
933
    (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*)
934
    => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
935
    (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
936
    => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
937
938
    (ERROR_CHECK TUPLE context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
939
        -> ($( $e:expr ),*) $( $tail:tt )*)
940
    => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
941
    (ERROR_CHECK STRUCT context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
942
        -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
943
    => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
944
945
    (ERROR_CHECK $imode:tt ) => {};
946
    // Utility functions
947
    (IDENT $ident:ident) => { $ident }
948
}
949
950
/// Generic context type
951
///
952
/// Used mostly as a transport for `ResultExt::context` method
953
#[derive(Debug)]
954
pub struct Context<X, E>(pub X, pub E);
955
956
/// Result extension trait adding a `context` method
957
pub trait ResultExt<T, E> {
958
    /// The method is use to add context information to current operation
959
    ///
960
    /// The context data is then used in error constructor to store additional
961
    /// information within error. For example, you may add a filename as a
962
    /// context for file operation. See crate documentation for the actual
963
    /// example.
964
    fn context<X>(self, x: X) -> Result<T, Context<X, E>>;
965
}
966
967
impl<T, E> ResultExt<T, E> for Result<T, E> {
968
    fn context<X>(self, x: X) -> Result<T, Context<X, E>> {
969
        self.map_err(|e| Context(x, e))
970
    }
971
}
972
973
#[cfg(test)]
974
mod test {
975
    use std::error::Error;
976
    use std::num::{ParseFloatError, ParseIntError};
977
    use std::path::{Path, PathBuf};
978
    use std::str::Utf8Error;
979
    use std::string::FromUtf8Error;
980
981
    use super::ResultExt;
982
983
    quick_error! {
984
        #[derive(Debug)]
985
        pub enum Bare {
986
            One
987
            Two
988
        }
989
    }
990
991
    #[test]
992
    fn bare_item_direct() {
993
        assert_eq!(format!("{}", Bare::One), "One".to_string());
994
        assert_eq!(format!("{:?}", Bare::One), "One".to_string());
995
        assert!(Bare::One.source().is_none());
996
    }
997
998
    #[test]
999
    fn bare_item_trait() {
1000
        let err: &dyn Error = &Bare::Two;
1001
        assert_eq!(format!("{}", err), "Two".to_string());
1002
        assert_eq!(format!("{:?}", err), "Two".to_string());
1003
        assert!(err.source().is_none());
1004
    }
1005
1006
    quick_error! {
1007
        #[derive(Debug)]
1008
        pub enum Wrapper wraps Wrapped {
1009
            One
1010
            Two(s: String) {
1011
                display("two: {}", s)
1012
                from()
1013
            }
1014
        }
1015
    }
1016
1017
    #[test]
1018
    fn wrapper() {
1019
        assert_eq!(
1020
            format!("{}", Wrapper::from(Wrapped::One)),
1021
            "One".to_string()
1022
        );
1023
        assert_eq!(
1024
            format!("{}", Wrapper::from(Wrapped::from(String::from("hello")))),
1025
            "two: hello".to_string()
1026
        );
1027
        assert_eq!(
1028
            format!("{:?}", Wrapper::from(Wrapped::One)),
1029
            "Wrapper(One)".to_string()
1030
        );
1031
    }
1032
1033
    quick_error! {
1034
        #[derive(Debug, PartialEq)]
1035
        pub enum TupleWrapper {
1036
            /// ParseFloat Error
1037
            ParseFloatError(err: ParseFloatError) {
1038
                from()
1039
                display("parse float error: {err}", err=err)
1040
                source(err)
1041
            }
1042
            Other(descr: &'static str) {
1043
                display("Error: {}", descr)
1044
            }
1045
            /// FromUtf8 Error
1046
            FromUtf8Error(err: Utf8Error, source: Vec<u8>) {
1047
                source(err)
1048
                display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err)
1049
                from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes())
1050
            }
1051
            Discard {
1052
                from(&'static str)
1053
            }
1054
            Singleton {
1055
                display("Just a string")
1056
            }
1057
        }
1058
    }
1059
1060
    #[test]
1061
    fn tuple_wrapper_err() {
1062
        let source = "one and a half times pi".parse::<f32>().unwrap_err();
1063
        let err = TupleWrapper::ParseFloatError(source.clone());
1064
        assert_eq!(format!("{}", err), format!("parse float error: {}", source));
1065
        assert_eq!(
1066
            format!("{:?}", err),
1067
            format!("ParseFloatError({:?})", source)
1068
        );
1069
        assert_eq!(
1070
            format!("{:?}", err.source().unwrap()),
1071
            format!("{:?}", source)
1072
        );
1073
    }
1074
1075
    #[test]
1076
    fn tuple_wrapper_trait_str() {
1077
        let desc = "hello";
1078
        let err: &dyn Error = &TupleWrapper::Other(desc);
1079
        assert_eq!(format!("{}", err), format!("Error: {}", desc));
1080
        assert_eq!(format!("{:?}", err), format!("Other({:?})", desc));
1081
        assert!(err.source().is_none());
1082
    }
1083
1084
    #[test]
1085
    fn tuple_wrapper_trait_two_fields() {
1086
        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1087
        let source = String::from_utf8(invalid_utf8.clone())
1088
            .unwrap_err()
1089
            .utf8_error();
1090
        let err: &dyn Error = &TupleWrapper::FromUtf8Error(source.clone(), invalid_utf8.clone());
1091
        assert_eq!(
1092
            format!("{}", err),
1093
            format!(
1094
                "{desc} at index {pos}: {source}",
1095
                desc = "utf8 error",
1096
                pos = source.valid_up_to(),
1097
                source = source
1098
            )
1099
        );
1100
        assert_eq!(
1101
            format!("{:?}", err),
1102
            format!("FromUtf8Error({:?}, {:?})", source, invalid_utf8)
1103
        );
1104
        assert_eq!(
1105
            format!("{:?}", err.source().unwrap()),
1106
            format!("{:?}", source)
1107
        );
1108
    }
1109
1110
    #[test]
1111
    fn tuple_wrapper_from() {
1112
        let source = "one and a half times pi".parse::<f32>().unwrap_err();
1113
        let err = TupleWrapper::ParseFloatError(source.clone());
1114
        let err_from: TupleWrapper = From::from(source);
1115
        assert_eq!(err_from, err);
1116
    }
1117
1118
    #[test]
1119
    fn tuple_wrapper_custom_from() {
1120
        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1121
        let source = String::from_utf8(invalid_utf8.clone()).unwrap_err();
1122
        let err = TupleWrapper::FromUtf8Error(source.utf8_error().clone(), invalid_utf8);
1123
        let err_from: TupleWrapper = From::from(source);
1124
        assert_eq!(err_from, err);
1125
    }
1126
1127
    #[test]
1128
    fn tuple_wrapper_discard() {
1129
        let err: TupleWrapper = From::from("hello");
1130
        assert_eq!(format!("{}", err), format!("Discard"));
1131
        assert_eq!(format!("{:?}", err), format!("Discard"));
1132
        assert!(err.source().is_none());
1133
    }
1134
1135
    #[test]
1136
    fn tuple_wrapper_singleton() {
1137
        let err: TupleWrapper = TupleWrapper::Singleton;
1138
        assert_eq!(format!("{}", err), format!("Just a string"));
1139
        assert_eq!(format!("{:?}", err), format!("Singleton"));
1140
        assert!(err.source().is_none());
1141
    }
1142
1143
    quick_error! {
1144
        #[derive(Debug, PartialEq)]
1145
        pub enum StructWrapper {
1146
            // Utf8 Error
1147
            Utf8Error{ err: Utf8Error, hint: Option<&'static str> } {
1148
                source(err)
1149
                display(me) -> ("{desc} at index {pos}: {err}", desc="utf8 error", pos=err.valid_up_to(), err=err)
1150
                from(err: Utf8Error) -> { err: err, hint: None }
1151
            }
1152
            // Utf8 Error
1153
            ExcessComma { descr: &'static str, } {
1154
                display("Error: {}", descr)
1155
            }
1156
        }
1157
    }
1158
1159
    #[test]
1160
    fn struct_wrapper_err() {
1161
        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1162
        let source = String::from_utf8(invalid_utf8.clone())
1163
            .unwrap_err()
1164
            .utf8_error();
1165
        let err: &dyn Error = &StructWrapper::Utf8Error {
1166
            err: source.clone(),
1167
            hint: Some("nonsense"),
1168
        };
1169
        assert_eq!(
1170
            format!("{}", err),
1171
            format!(
1172
                "{desc} at index {pos}: {source}",
1173
                desc = "utf8 error",
1174
                pos = source.valid_up_to(),
1175
                source = source
1176
            )
1177
        );
1178
        assert_eq!(
1179
            format!("{:?}", err),
1180
            format!(
1181
                "Utf8Error {{ err: {:?}, hint: {:?} }}",
1182
                source,
1183
                Some("nonsense")
1184
            )
1185
        );
1186
        assert_eq!(
1187
            format!("{:?}", err.source().unwrap()),
1188
            format!("{:?}", source)
1189
        );
1190
    }
1191
1192
    #[test]
1193
    fn struct_wrapper_struct_from() {
1194
        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1195
        let source = String::from_utf8(invalid_utf8.clone())
1196
            .unwrap_err()
1197
            .utf8_error();
1198
        let err = StructWrapper::Utf8Error {
1199
            err: source.clone(),
1200
            hint: None,
1201
        };
1202
        let err_from: StructWrapper = From::from(source);
1203
        assert_eq!(err_from, err);
1204
    }
1205
1206
    #[test]
1207
    fn struct_wrapper_excess_comma() {
1208
        let descr = "hello";
1209
        let err = StructWrapper::ExcessComma { descr: descr };
1210
        assert_eq!(format!("{}", err), format!("Error: {}", descr));
1211
        assert_eq!(
1212
            format!("{:?}", err),
1213
            format!("ExcessComma {{ descr: {:?} }}", descr)
1214
        );
1215
        assert!(err.source().is_none());
1216
    }
1217
1218
    quick_error! {
1219
        #[derive(Debug)]
1220
        pub enum ContextErr {
1221
            Float(src: String, err: ParseFloatError) {
1222
                context(s: &'a str, e: ParseFloatError) -> (s.to_string(), e)
1223
                display("Float error {:?}: {}", src, err)
1224
            }
1225
            Int { src: String, err: ParseIntError } {
1226
                context(s: &'a str, e: ParseIntError)
1227
                    -> {src: s.to_string(), err: e}
1228
                display("Int error {:?}: {}", src, err)
1229
            }
1230
            Utf8(path: PathBuf, err: Utf8Error) {
1231
                context(p: AsRef<Path>, e: Utf8Error)
1232
                    -> (p.as_ref().to_path_buf(), e)
1233
                display("Path error at {:?}: {}", path, err)
1234
            }
1235
            Utf8Str(s: String, err: ::std::io::Error) {
1236
                context(s: AsRef<str>, e: ::std::io::Error)
1237
                    -> (s.as_ref().to_string(), e)
1238
                display("Str error {:?}: {}", s, err)
1239
            }
1240
        }
1241
    }
1242
1243
    #[test]
1244
    fn parse_float_error() {
1245
        fn parse_float(s: &str) -> Result<f32, ContextErr> {
1246
            Ok(s.parse().context(s)?)
1247
        }
1248
        assert_eq!(
1249
            format!("{}", parse_float("12ab").unwrap_err()),
1250
            r#"Float error "12ab": invalid float literal"#
1251
        );
1252
    }
1253
1254
    #[test]
1255
    fn parse_int_error() {
1256
        fn parse_int(s: &str) -> Result<i32, ContextErr> {
1257
            Ok(s.parse().context(s)?)
1258
        }
1259
        assert_eq!(
1260
            format!("{}", parse_int("12.5").unwrap_err()),
1261
            r#"Int error "12.5": invalid digit found in string"#
1262
        );
1263
    }
1264
1265
    #[test]
1266
    fn debug_context() {
1267
        fn parse_int(s: &str) -> i32 {
1268
            s.parse().context(s).unwrap()
1269
        }
1270
        assert_eq!(parse_int("12"), 12);
1271
        assert_eq!(
1272
            format!("{:?}", "x".parse::<i32>().context("x")),
1273
            r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"#
1274
        );
1275
    }
1276
1277
    #[test]
1278
    fn path_context() {
1279
        fn parse_utf<P: AsRef<Path>>(s: &[u8], p: P) -> Result<(), ContextErr> {
1280
            ::std::str::from_utf8(s).context(p)?;
1281
            Ok(())
1282
        }
1283
        let etext = parse_utf(b"a\x80\x80", "/etc").unwrap_err().to_string();
1284
        assert!(etext.starts_with("Path error at \"/etc\": invalid utf-8"));
1285
        let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp"))
1286
            .unwrap_err()
1287
            .to_string();
1288
        assert!(etext.starts_with("Path error at \"/tmp\": invalid utf-8"));
1289
    }
1290
1291
    #[test]
1292
    fn conditional_compilation() {
1293
        quick_error! {
1294
            #[allow(dead_code)]
1295
            #[derive(Debug)]
1296
            pub enum Test {
1297
                #[cfg(feature = "foo")]
1298
                Variant
1299
            }
1300
        }
1301
    }
1302
1303
    #[test]
1304
    #[allow(deprecated)]
1305
    fn cause_struct_wrapper_err() {
1306
        let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1307
        let cause = String::from_utf8(invalid_utf8.clone())
1308
            .unwrap_err()
1309
            .utf8_error();
1310
        let err: &dyn Error = &StructWrapper::Utf8Error {
1311
            err: cause.clone(),
1312
            hint: Some("nonsense"),
1313
        };
1314
        assert_eq!(
1315
            format!("{}", err),
1316
            format!(
1317
                "{desc} at index {pos}: {cause}",
1318
                desc = "utf8 error",
1319
                pos = cause.valid_up_to(),
1320
                cause = cause
1321
            )
1322
        );
1323
        assert_eq!(
1324
            format!("{:?}", err),
1325
            format!(
1326
                "Utf8Error {{ err: {:?}, hint: {:?} }}",
1327
                cause,
1328
                Some("nonsense")
1329
            )
1330
        );
1331
        assert_eq!(
1332
            format!("{:?}", err.cause().unwrap()),
1333
            format!("{:?}", cause)
1334
        );
1335
    }
1336
}