1 // From https://github.com/tailhook/quick-error
3 // - replace `impl Error` by `impl Item::description`
7 macro_rules
! quick_error
{
9 pub enum $name
:ident { $($chunks:tt)* }
11 quick_error
!(SORT
[pub enum $name $
(#[$meta])* ]
13 queue
[ $
($chunks
)* ]);
16 enum $name
:ident { $($chunks:tt)* }
18 quick_error
!(SORT
[enum $name $
(#[$meta])* ]
20 queue
[ $
($chunks
)* ]);
22 // Queue is empty, can do the work
23 (SORT
[enum $name
:ident $
( #[$meta:meta] )*]
24 items
[$
($
( #[$imeta:meta] )*
25 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
26 {$( $ifuncs:tt )*}
)* ]
30 quick_error
!(ENUM_DEFINITION
[enum $name $
( #[$meta] )*]
32 queue
[$
($
( #[$imeta] )*
33 => $iitem
: $imode
[$
( $ivar
: $ityp
),*] )*]
35 quick_error
!(IMPLEMENTATIONS $name
{$
(
36 $iitem
: $imode
[$
(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
39 quick_error
!(ERROR_CHECK $imode $
($ifuncs
)*);
42 (SORT
[pub enum $name
:ident $
( #[$meta:meta] )*]
43 items
[$
($
( #[$imeta:meta] )*
44 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
45 {$( $ifuncs:tt )*}
)* ]
49 quick_error
!(ENUM_DEFINITION
[pub enum $name $
( #[$meta] )*]
51 queue
[$
($
( #[$imeta] )*
52 => $iitem
: $imode
[$
( $ivar
: $ityp
),*] )*]
54 quick_error
!(IMPLEMENTATIONS $name
{$
(
55 $iitem
: $imode
[$
(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
58 quick_error
!(ERROR_CHECK $imode $
($ifuncs
)*);
63 items
[$
($
( #[$imeta:meta] )*
64 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
65 {$( $ifuncs:tt )*}
)* ]
66 buf
[$
( #[$bmeta:meta] )*]
67 queue
[ #[$qmeta:meta] $( $tail:tt )*]
69 quick_error
!(SORT
[$
( $def
)*]
70 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
71 buf
[$
( #[$bmeta] )* #[$qmeta] ]
74 // Add ident to buffer
76 items
[$
($
( #[$imeta:meta] )*
77 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
78 {$( $ifuncs:tt )*}
)* ]
79 buf
[$
( #[$bmeta:meta] )*]
80 queue
[ $qitem
:ident $
( $tail
:tt
)*]
82 quick_error
!(SORT
[$
( $def
)*]
83 items
[$
( $
(#[$imeta])*
84 => $iitem
: $imode
[$
( $ivar
:$ityp
),*] {$( $ifuncs )*}
)*]
85 buf
[$
(#[$bmeta])* => $qitem : UNIT [ ] ]
88 // Flush buffer on meta after ident
90 items
[$
($
( #[$imeta:meta] )*
91 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
92 {$( $ifuncs:tt )*}
)* ]
93 buf
[$
( #[$bmeta:meta] )*
94 => $bitem
:ident
: $bmode
:tt
[$
( $bvar
:ident
: $btyp
:ty
),*] ]
95 queue
[ #[$qmeta:meta] $( $tail:tt )*]
97 quick_error
!(SORT
[$
( $def
)*]
98 enum [$
( $
(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
99 $
(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
100 items
[$
($
( #[$imeta:meta] )*
101 => $iitem
: $imode
[$
( $ivar
:$ityp
),*] {$( $ifuncs )*}
)*
102 $bitem
: $bmode
[$
( $bvar
:$btyp
),*] {}
]
104 queue
[$
( $tail
)*]);
106 // Add tuple enum-variant
107 (SORT
[$
( $def
:tt
)*]
108 items
[$
($
( #[$imeta:meta] )*
109 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
110 {$( $ifuncs:tt )*}
)* ]
111 buf
[$
( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
112 queue
[($
( $qvar
:ident
: $qtyp
:ty
),+) $
( $tail
:tt
)*]
114 quick_error
!(SORT
[$
( $def
)*]
115 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
116 buf
[$
( #[$bmeta] )* => $bitem: TUPLE [$( $qvar:$qtyp ),*] ]
120 // Add struct enum-variant - e.g. { descr: &'static str }
121 (SORT
[$
( $def
:tt
)*]
122 items
[$
($
( #[$imeta:meta] )*
123 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
124 {$( $ifuncs:tt )*}
)* ]
125 buf
[$
( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
126 queue
[{ $( $qvar:ident: $qtyp:ty ),+} $
( $tail
:tt
)*]
128 quick_error
!(SORT
[$
( $def
)*]
129 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
130 buf
[$
( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
131 queue
[$
( $tail
)*]);
133 // Add struct enum-variant, with excess comma - e.g. { descr: &'static str, }
134 (SORT
[$
( $def
:tt
)*]
135 items
[$
($
( #[$imeta:meta] )*
136 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
137 {$( $ifuncs:tt )*}
)* ]
138 buf
[$
( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
139 queue
[{$( $qvar:ident: $qtyp:ty ),+ ,} $
( $tail
:tt
)*]
141 quick_error
!(SORT
[$
( $def
)*]
142 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
143 buf
[$
( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
144 queue
[$
( $tail
)*]);
146 // Add braces and flush always on braces
147 (SORT
[$
( $def
:tt
)*]
148 items
[$
($
( #[$imeta:meta] )*
149 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
150 {$( $ifuncs:tt )*}
)* ]
151 buf
[$
( #[$bmeta:meta] )*
152 => $bitem
:ident
: $bmode
:tt
[$
( $bvar
:ident
: $btyp
:ty
),*] ]
153 queue
[ {$( $qfuncs:tt )*} $
( $tail
:tt
)*]
155 quick_error
!(SORT
[$
( $def
)*]
156 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
157 $
(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ]
159 queue
[$
( $tail
)*]);
161 // Flush buffer on double ident
162 (SORT
[$
( $def
:tt
)*]
163 items
[$
($
( #[$imeta:meta] )*
164 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
165 {$( $ifuncs:tt )*}
)* ]
166 buf
[$
( #[$bmeta:meta] )*
167 => $bitem
:ident
: $bmode
:tt
[$
( $bvar
:ident
: $btyp
:ty
),*] ]
168 queue
[ $qitem
:ident $
( $tail
:tt
)*]
170 quick_error
!(SORT
[$
( $def
)*]
171 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
172 $
(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
173 buf
[ => $qitem
: UNIT
[ ] ]
174 queue
[$
( $tail
)*]);
176 // Flush buffer on end
177 (SORT
[$
( $def
:tt
)*]
178 items
[$
($
( #[$imeta:meta] )*
179 => $iitem
:ident
: $imode
:tt
[$
( $ivar
:ident
: $ityp
:ty
),*]
180 {$( $ifuncs:tt )*}
)* ]
181 buf
[$
( #[$bmeta:meta] )*
182 => $bitem
:ident
: $bmode
:tt
[$
( $bvar
:ident
: $btyp
:ty
),*] ]
185 quick_error
!(SORT
[$
( $def
)*]
186 items
[$
( $
(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
187 $
(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
191 // Public enum (Queue Empty)
192 (ENUM_DEFINITION
[pub enum $name
:ident $
( #[$meta:meta] )*]
193 body
[$
($
( #[$imeta:meta] )*
194 => $iitem
:ident ($
(($
( $ttyp
:ty
),+))*) {$({$( $svar:ident: $styp:ty ),*}
)*} )* ]
201 $iitem $
(($
( $ttyp
),*))* $
({$( $svar: $styp ),*}
)*,
205 // Private enum (Queue Empty)
206 (ENUM_DEFINITION
[enum $name
:ident $
( #[$meta:meta] )*]
207 body
[$
($
( #[$imeta:meta] )*
208 => $iitem
:ident ($
(($
( $ttyp
:ty
),+))*) {$({$( $svar:ident: $styp:ty ),*}
)*} )* ]
215 $iitem $
(($
( $ttyp
),*))* $
({$( $svar: $styp ),*}
)*,
220 (ENUM_DEFINITION
[$
( $def
:tt
)*]
221 body
[$
($
( #[$imeta:meta] )*
222 => $iitem
:ident ($
(($
( $ttyp
:ty
),+))*) {$({$( $svar:ident: $styp:ty ),*}
)*} )* ]
223 queue
[$
( #[$qmeta:meta] )*
224 => $qitem
:ident
: UNIT
[ ] $
( $queue
:tt
)*]
226 quick_error
!(ENUM_DEFINITION
[ $
($def
)* ]
227 body
[$
($
( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
228 $
( #[$qmeta] )* => $qitem () {} ]
233 (ENUM_DEFINITION
[$
( $def
:tt
)*]
234 body
[$
($
( #[$imeta:meta] )*
235 => $iitem
:ident ($
(($
( $ttyp
:ty
),+))*) {$({$( $svar:ident: $styp:ty ),*}
)*} )* ]
236 queue
[$
( #[$qmeta:meta] )*
237 => $qitem
:ident
: TUPLE
[$
( $qvar
:ident
: $qtyp
:ty
),+] $
( $queue
:tt
)*]
239 quick_error
!(ENUM_DEFINITION
[ $
($def
)* ]
240 body
[$
($
( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
241 $
( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
246 (ENUM_DEFINITION
[$
( $def
:tt
)*]
247 body
[$
($
( #[$imeta:meta] )*
248 => $iitem
:ident ($
(($
( $ttyp
:ty
),+))*) {$({$( $svar:ident: $styp:ty ),*}
)*} )* ]
249 queue
[$
( #[$qmeta:meta] )*
250 => $qitem
:ident
: STRUCT
[$
( $qvar
:ident
: $qtyp
:ty
),*] $
( $queue
:tt
)*]
252 quick_error
!(ENUM_DEFINITION
[ $
($def
)* ]
253 body
[$
($
( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
254 $
( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ]
260 $item
:ident
: $imode
:tt
[$
(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
264 impl ::std
::fmt
::Display
for $name
{
265 fn fmt(&self, fmt
: &mut ::std
::fmt
::Formatter
)
266 -> ::std
::fmt
::Result
271 quick_error
!(ITEM_PATTERN
272 $name $item
: $imode
[$
( ref $var
),*]
274 let display_fn
= quick_error
!(FIND_DISPLAY_IMPL
278 display_fn(self, fmt
)
285 impl ::std::error::Error for $name {
286 fn description(&self) -> &str {
289 quick_error!(ITEM_PATTERN
290 $name $item: $imode [$( ref $var ),*]
292 quick_error!(FIND_DESCRIPTION_IMPL
293 $item: $imode self fmt [$( $var ),*]
299 fn cause(&self) -> Option<&::std::error::Error> {
302 quick_error!(ITEM_PATTERN
303 $name $item: $imode [$( ref $var ),*]
305 quick_error!(FIND_CAUSE_IMPL
306 $item: $imode [$( $var ),*]
315 /// A string describing the error kind.
316 pub fn description(&self) -> &str {
320 quick_error
!(ITEM_PATTERN
321 $name $item
: $imode
[$
( ref $var
),*]
323 quick_error
!(FIND_DESCRIPTION_IMPL
324 $item
: $imode
self fmt
[$
( $var
),*]
332 quick_error
!(FIND_FROM_IMPL
333 $name $item
: $imode
[$
( $var
:$typ
),*]
337 (FIND_DISPLAY_IMPL $name
:ident $item
:ident
: $imode
:tt
338 { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
340 |quick_error
!(IDENT $self_
): &$name
, f
: &mut ::std
::fmt
::Formatter
| {
341 write
!(f
, $
( $exprs
)*)
344 (FIND_DISPLAY_IMPL $name
:ident $item
:ident
: $imode
:tt
345 { display($pattern:expr) $( $tail:tt )*}
347 |_
, f
: &mut ::std
::fmt
::Formatter
| { write!(f, $pattern) }
349 (FIND_DISPLAY_IMPL $name
:ident $item
:ident
: $imode
:tt
350 { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
352 |_
, f
: &mut ::std
::fmt
::Formatter
| { write!(f, $pattern, $( $exprs )*) }
354 (FIND_DISPLAY_IMPL $name
:ident $item
:ident
: $imode
:tt
355 { $t:tt $( $tail:tt )*}
357 quick_error
!(FIND_DISPLAY_IMPL
361 (FIND_DISPLAY_IMPL $name
:ident $item
:ident
: $imode
:tt
364 |self_
: &$name
, f
: &mut ::std
::fmt
::Formatter
| {
365 write
!(f
, "{}", self_
.description())
368 (FIND_DESCRIPTION_IMPL $item
:ident
: $imode
:tt $me
:ident $fmt
:ident
370 { description($expr:expr) $( $tail:tt )*}
374 (FIND_DESCRIPTION_IMPL $item
:ident
: $imode
:tt $me
:ident $fmt
:ident
376 { $t:tt $( $tail:tt )*}
378 quick_error
!(FIND_DESCRIPTION_IMPL
379 $item
: $imode $me $fmt
[$
( $var
),*]
382 (FIND_DESCRIPTION_IMPL $item
:ident
: $imode
:tt $me
:ident $fmt
:ident
388 (FIND_CAUSE_IMPL $item
:ident
: $imode
:tt
390 { cause($expr:expr) $( $tail:tt )*}
394 (FIND_CAUSE_IMPL $item
:ident
: $imode
:tt
396 { $t:tt $( $tail:tt )*}
398 quick_error
!(FIND_CAUSE_IMPL
399 $item
: $imode
[$
( $var
),*]
402 (FIND_CAUSE_IMPL $item
:ident
: $imode
:tt
408 (FIND_FROM_IMPL $name
:ident $item
:ident
: $imode
:tt
409 [$
( $var
:ident
: $typ
:ty
),*]
410 { from() $( $tail:tt )*}
413 impl From
<$typ
> for $name
{
414 fn from($var
: $typ
) -> $name
{
419 quick_error
!(FIND_FROM_IMPL
420 $name $item
: $imode
[$
( $var
:$typ
),*]
423 (FIND_FROM_IMPL $name
:ident $item
:ident
: UNIT
425 { from($ftyp:ty) $( $tail:tt )*}
427 impl From
<$ftyp
> for $name
{
428 fn from(_discarded_error
: $ftyp
) -> $name
{
432 quick_error
!(FIND_FROM_IMPL
433 $name $item
: UNIT
[ ]
436 (FIND_FROM_IMPL $name
:ident $item
:ident
: TUPLE
437 [$
( $var
:ident
: $typ
:ty
),*]
438 { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
440 impl From
<$ftyp
> for $name
{
441 fn from($fvar
: $ftyp
) -> $name
{
442 $name
::$
item($
( $texpr
),*)
445 quick_error
!(FIND_FROM_IMPL
446 $name $item
: TUPLE
[$
( $var
:$typ
),*]
449 (FIND_FROM_IMPL $name
:ident $item
:ident
: STRUCT
450 [$
( $var
:ident
: $typ
:ty
),*]
451 { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $
( $tail
:tt
)*}
453 impl From
<$ftyp
> for $name
{
454 fn from($fvar
: $ftyp
) -> $name
{
460 quick_error
!(FIND_FROM_IMPL
461 $name $item
: STRUCT
[$
( $var
:$typ
),*]
464 (FIND_FROM_IMPL $name
:ident $item
:ident
: $imode
:tt
465 [$
( $var
:ident
: $typ
:ty
),*]
466 { $t:tt $( $tail:tt )*}
468 quick_error
!(FIND_FROM_IMPL
469 $name $item
: $imode
[$
( $var
:$typ
),*]
473 (FIND_FROM_IMPL $name
:ident $item
:ident
: $imode
:tt
474 [$
( $var
:ident
: $typ
:ty
),*]
478 (ITEM_BODY $
(#[$imeta:meta])* $item:ident: UNIT
480 (ITEM_BODY $
(#[$imeta:meta])* $item:ident: TUPLE
485 (ITEM_BODY $
(#[$imeta:meta])* $item:ident: STRUCT
486 [$
( $var
:ident
: $typ
:ty
),*]
490 (ITEM_PATTERN $name
:ident $item
:ident
: UNIT
[]
494 (ITEM_PATTERN $name
:ident $item
:ident
: TUPLE
495 [$
( ref $var
:ident
),*]
497 $name
::$
item ($
( ref $var
),*)
499 (ITEM_PATTERN $name
:ident $item
:ident
: STRUCT
500 [$
( ref $var
:ident
),*]
502 $name
::$item {$( ref $var ),*}
504 // This one should match all allowed sequences in "funcs" but not match
506 // This is to contrast FIND_* clauses which just find stuff they need and
507 // skip everything else completely
508 (ERROR_CHECK $imode
:tt
display($self_
:tt
) -> ($
( $exprs
:tt
)*) $
( $tail
:tt
)*)
509 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
510 (ERROR_CHECK $imode
:tt
display($pattern
: expr
) $
( $tail
:tt
)*)
511 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
512 (ERROR_CHECK $imode
:tt
display($pattern
: expr
, $
( $exprs
:tt
)*) $
( $tail
:tt
)*)
513 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
514 (ERROR_CHECK $imode
:tt
description($expr
:expr
) $
( $tail
:tt
)*)
515 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
516 (ERROR_CHECK $imode
:tt
cause($expr
:expr
) $
($tail
:tt
)*)
517 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
518 (ERROR_CHECK $imode
:tt
from() $
($tail
:tt
)*)
519 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
520 (ERROR_CHECK $imode
:tt
from($ftyp
:ty
) $
($tail
:tt
)*)
521 => { quick_error!(ERROR_CHECK $imode $($tail)*); }
;
522 (ERROR_CHECK TUPLE
from($fvar
:ident
: $ftyp
:ty
) -> ($
( $e
:expr
),*) $
( $tail
:tt
)*)
523 => { quick_error!(ERROR_CHECK TUPLE $($tail)*); }
;
524 (ERROR_CHECK STRUCT
from($fvar
:ident
: $ftyp
:ty
) -> {$( $v:ident: $e:expr ),*} $
( $tail
:tt
)*)
525 => { quick_error!(ERROR_CHECK STRUCT $($tail)*); }
;
526 (ERROR_CHECK $imode
:tt
) => {}
;
528 (IDENT $ident
:ident
) => { $ident }