1#![warn(missing_docs)]
2#[macro_export]
307macro_rules! quick_error {
308
309 ( $(#[$meta:meta])*
310 pub enum $name:ident { $($chunks:tt)* }
311 ) => {
312 quick_error!(SORT [pub enum $name $(#[$meta])* ]
313 items [] buf []
314 queue [ $($chunks)* ]);
315 };
316 ( $(#[$meta:meta])*
317 enum $name:ident { $($chunks:tt)* }
318 ) => {
319 quick_error!(SORT [enum $name $(#[$meta])* ]
320 items [] buf []
321 queue [ $($chunks)* ]);
322 };
323
324 ( $(#[$meta:meta])*
325 pub enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
326 ) => {
327 quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
328 quick_error!(SORT [enum $enum_name $(#[$meta])* ]
329 items [] buf []
330 queue [ $($chunks)* ]);
331 };
332
333 ( $(#[$meta:meta])*
334 pub enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
335 ) => {
336 quick_error!(WRAPPER $enum_name [ pub struct ] $name $(#[$meta])*);
337 quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
338 items [] buf []
339 queue [ $($chunks)* ]);
340 };
341 ( $(#[$meta:meta])*
342 enum $name:ident wraps $enum_name:ident { $($chunks:tt)* }
343 ) => {
344 quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
345 quick_error!(SORT [enum $enum_name $(#[$meta])* ]
346 items [] buf []
347 queue [ $($chunks)* ]);
348 };
349
350 ( $(#[$meta:meta])*
351 enum $name:ident wraps pub $enum_name:ident { $($chunks:tt)* }
352 ) => {
353 quick_error!(WRAPPER $enum_name [ struct ] $name $(#[$meta])*);
354 quick_error!(SORT [pub enum $enum_name $(#[$meta])* ]
355 items [] buf []
356 queue [ $($chunks)* ]);
357 };
358
359
360 (
361 WRAPPER $internal:ident [ $($strdef:tt)* ] $strname:ident
362 $(#[$meta:meta])*
363 ) => {
364 $(#[$meta])*
365 $($strdef)* $strname ( $internal );
366
367 impl ::std::fmt::Display for $strname {
368 fn fmt(&self, f: &mut ::std::fmt::Formatter)
369 -> ::std::fmt::Result
370 {
371 ::std::fmt::Display::fmt(&self.0, f)
372 }
373 }
374
375 impl From<$internal> for $strname {
376 fn from(err: $internal) -> Self {
377 $strname(err)
378 }
379 }
380
381 impl ::std::error::Error for $strname {
382 fn description(&self) -> &str {
383 self.0.description()
384 }
385 fn cause(&self) -> Option<&::std::error::Error> {
386 self.0.cause()
387 }
388 }
389 };
390
391 (SORT [enum $name:ident $( #[$meta:meta] )*]
393 items [$($( #[$imeta:meta] )*
394 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
395 {$( $ifuncs:tt )*} )* ]
396 buf [ ]
397 queue [ ]
398 ) => {
399 quick_error!(ENUM_DEFINITION [enum $name $( #[$meta] )*]
400 body []
401 queue [$($( #[$imeta] )*
402 => $iitem: $imode [$( $ivar: $ityp ),*] )*]
403 );
404 quick_error!(IMPLEMENTATIONS $name {$(
405 $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
406 )*});
407 $(
408 quick_error!(ERROR_CHECK $imode $($ifuncs)*);
409 )*
410 };
411 (SORT [pub enum $name:ident $( #[$meta:meta] )*]
412 items [$($( #[$imeta:meta] )*
413 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
414 {$( $ifuncs:tt )*} )* ]
415 buf [ ]
416 queue [ ]
417 ) => {
418 quick_error!(ENUM_DEFINITION [pub enum $name $( #[$meta] )*]
419 body []
420 queue [$($( #[$imeta] )*
421 => $iitem: $imode [$( $ivar: $ityp ),*] )*]
422 );
423 quick_error!(IMPLEMENTATIONS $name {$(
424 $iitem: $imode [$(#[$imeta])*] [$( $ivar: $ityp ),*] {$( $ifuncs )*}
425 )*});
426 $(
427 quick_error!(ERROR_CHECK $imode $($ifuncs)*);
428 )*
429 };
430 (SORT [$( $def:tt )*]
432 items [$($( #[$imeta:meta] )*
433 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
434 {$( $ifuncs:tt )*} )* ]
435 buf [$( #[$bmeta:meta] )*]
436 queue [ #[$qmeta:meta] $( $tail:tt )*]
437 ) => {
438 quick_error!(SORT [$( $def )*]
439 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
440 buf [$( #[$bmeta] )* #[$qmeta] ]
441 queue [$( $tail )*]);
442 };
443 (SORT [$( $def:tt )*]
445 items [$($( #[$imeta:meta] )*
446 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
447 {$( $ifuncs:tt )*} )* ]
448 buf [$( #[$bmeta:meta] )*]
449 queue [ $qitem:ident $( $tail:tt )*]
450 ) => {
451 quick_error!(SORT [$( $def )*]
452 items [$( $(#[$imeta])*
453 => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
454 buf [$(#[$bmeta])* => $qitem : UNIT [ ] ]
455 queue [$( $tail )*]);
456 };
457 (SORT [$( $def:tt )*]
459 items [$($( #[$imeta:meta] )*
460 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
461 {$( $ifuncs:tt )*} )* ]
462 buf [$( #[$bmeta:meta] )*
463 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
464 queue [ #[$qmeta:meta] $( $tail:tt )*]
465 ) => {
466 quick_error!(SORT [$( $def )*]
467 enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
468 $(#[$bmeta])* => $bitem: $bmode $(( $($btyp),* ))*]
469 items [$($( #[$imeta:meta] )*
470 => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
471 $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
472 buf [ #[$qmeta] ]
473 queue [$( $tail )*]);
474 };
475 (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: TUPLE [$( $qvar:$qtyp ),*] ]
486 queue [$( $tail )*]
487 );
488 };
489 (SORT [$( $def:tt )*]
491 items [$($( #[$imeta:meta] )*
492 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
493 {$( $ifuncs:tt )*} )* ]
494 buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
495 queue [{ $( $qvar:ident: $qtyp:ty ),+} $( $tail:tt )*]
496 ) => {
497 quick_error!(SORT [$( $def )*]
498 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
499 buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
500 queue [$( $tail )*]);
501 };
502 (SORT [$( $def:tt )*]
504 items [$($( #[$imeta:meta] )*
505 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
506 {$( $ifuncs:tt )*} )* ]
507 buf [$( #[$bmeta:meta] )* => $bitem:ident: UNIT [ ] ]
508 queue [{$( $qvar:ident: $qtyp:ty ),+ ,} $( $tail:tt )*]
509 ) => {
510 quick_error!(SORT [$( $def )*]
511 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*]
512 buf [$( #[$bmeta] )* => $bitem: STRUCT [$( $qvar:$qtyp ),*] ]
513 queue [$( $tail )*]);
514 };
515 (SORT [$( $def:tt )*]
517 items [$($( #[$imeta:meta] )*
518 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
519 {$( $ifuncs:tt )*} )* ]
520 buf [$( #[$bmeta:meta] )*
521 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
522 queue [ {$( $qfuncs:tt )*} $( $tail:tt )*]
523 ) => {
524 quick_error!(SORT [$( $def )*]
525 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
526 $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {$( $qfuncs )*} ]
527 buf [ ]
528 queue [$( $tail )*]);
529 };
530 (SORT [$( $def:tt )*]
532 items [$($( #[$imeta:meta] )*
533 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
534 {$( $ifuncs:tt )*} )* ]
535 buf [$( #[$bmeta:meta] )*
536 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
537 queue [ $qitem:ident $( $tail:tt )*]
538 ) => {
539 quick_error!(SORT [$( $def )*]
540 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
541 $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
542 buf [ => $qitem : UNIT [ ] ]
543 queue [$( $tail )*]);
544 };
545 (SORT [$( $def:tt )*]
547 items [$($( #[$imeta:meta] )*
548 => $iitem:ident: $imode:tt [$( $ivar:ident: $ityp:ty ),*]
549 {$( $ifuncs:tt )*} )* ]
550 buf [$( #[$bmeta:meta] )*
551 => $bitem:ident: $bmode:tt [$( $bvar:ident: $btyp:ty ),*] ]
552 queue [ ]
553 ) => {
554 quick_error!(SORT [$( $def )*]
555 items [$( $(#[$imeta])* => $iitem: $imode [$( $ivar:$ityp ),*] {$( $ifuncs )*} )*
556 $(#[$bmeta])* => $bitem: $bmode [$( $bvar:$btyp ),*] {} ]
557 buf [ ]
558 queue [ ]);
559 };
560 (ENUM_DEFINITION [pub enum $name:ident $( #[$meta:meta] )*]
562 body [$($( #[$imeta:meta] )*
563 => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
564 queue [ ]
565 ) => {
566 #[allow(unknown_lints)] #[allow(renamed_and_removed_lints)]
568 #[allow(unused_doc_comment)]
569 #[allow(unused_doc_comments)]
570 $(#[$meta])*
571 pub enum $name {
572 $(
573 $(#[$imeta])*
574 $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
575 )*
576 }
577 };
578 (ENUM_DEFINITION [enum $name:ident $( #[$meta:meta] )*]
580 body [$($( #[$imeta:meta] )*
581 => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
582 queue [ ]
583 ) => {
584 #[allow(unknown_lints)] #[allow(renamed_and_removed_lints)]
586 #[allow(unused_doc_comment)]
587 #[allow(unused_doc_comments)]
588 $(#[$meta])*
589 enum $name {
590 $(
591 $(#[$imeta])*
592 $iitem $(($( $ttyp ),*))* $({$( $svar: $styp ),*})*,
593 )*
594 }
595 };
596 (ENUM_DEFINITION [$( $def:tt )*]
598 body [$($( #[$imeta:meta] )*
599 => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
600 queue [$( #[$qmeta:meta] )*
601 => $qitem:ident: UNIT [ ] $( $queue:tt )*]
602 ) => {
603 quick_error!(ENUM_DEFINITION [ $($def)* ]
604 body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
605 $( #[$qmeta] )* => $qitem () {} ]
606 queue [ $($queue)* ]
607 );
608 };
609 (ENUM_DEFINITION [$( $def:tt )*]
611 body [$($( #[$imeta:meta] )*
612 => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
613 queue [$( #[$qmeta:meta] )*
614 => $qitem:ident: TUPLE [$( $qvar:ident: $qtyp:ty ),+] $( $queue:tt )*]
615 ) => {
616 quick_error!(ENUM_DEFINITION [ $($def)* ]
617 body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
618 $( #[$qmeta] )* => $qitem (($( $qtyp ),*)) {} ]
619 queue [ $($queue)* ]
620 );
621 };
622 (ENUM_DEFINITION [$( $def:tt )*]
624 body [$($( #[$imeta:meta] )*
625 => $iitem:ident ($(($( $ttyp:ty ),+))*) {$({$( $svar:ident: $styp:ty ),*})*} )* ]
626 queue [$( #[$qmeta:meta] )*
627 => $qitem:ident: STRUCT [$( $qvar:ident: $qtyp:ty ),*] $( $queue:tt )*]
628 ) => {
629 quick_error!(ENUM_DEFINITION [ $($def)* ]
630 body [$($( #[$imeta] )* => $iitem ($(($( $ttyp ),+))*) {$({$( $svar: $styp ),*})*} )*
631 $( #[$qmeta] )* => $qitem () {{$( $qvar: $qtyp ),*}} ]
632 queue [ $($queue)* ]
633 );
634 };
635 (IMPLEMENTATIONS
636 $name:ident {$(
637 $item:ident: $imode:tt [$(#[$imeta:meta])*] [$( $var:ident: $typ:ty ),*] {$( $funcs:tt )*}
638 )*}
639 ) => {
640 #[allow(unused)]
641 #[allow(unknown_lints)] #[allow(renamed_and_removed_lints)]
643 #[allow(unused_doc_comment)]
644 #[allow(unused_doc_comments)]
645 impl ::std::fmt::Display for $name {
646 fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
647 -> ::std::fmt::Result
648 {
649 match *self {
650 $(
651 $(#[$imeta])*
652 quick_error!(ITEM_PATTERN
653 $name $item: $imode [$( ref $var ),*]
654 ) => {
655 let display_fn = quick_error!(FIND_DISPLAY_IMPL
656 $name $item: $imode
657 {$( $funcs )*});
658
659 display_fn(self, fmt)
660 }
661 )*
662 }
663 }
664 }
665 #[allow(unused)]
666 #[allow(unknown_lints)] #[allow(renamed_and_removed_lints)]
668 #[allow(unused_doc_comment)]
669 #[allow(unused_doc_comments)]
670 impl ::std::error::Error for $name {
671 fn description(&self) -> &str {
672 match *self {
673 $(
674 $(#[$imeta])*
675 quick_error!(ITEM_PATTERN
676 $name $item: $imode [$( ref $var ),*]
677 ) => {
678 quick_error!(FIND_DESCRIPTION_IMPL
679 $item: $imode self fmt [$( $var ),*]
680 {$( $funcs )*})
681 }
682 )*
683 }
684 }
685 fn cause(&self) -> Option<&::std::error::Error> {
686 match *self {
687 $(
688 $(#[$imeta])*
689 quick_error!(ITEM_PATTERN
690 $name $item: $imode [$( ref $var ),*]
691 ) => {
692 quick_error!(FIND_CAUSE_IMPL
693 $item: $imode [$( $var ),*]
694 {$( $funcs )*})
695 }
696 )*
697 }
698 }
699 }
700 $(
701 quick_error!(FIND_FROM_IMPL
702 $name $item: $imode [$( $var:$typ ),*]
703 {$( $funcs )*});
704 )*
705 $(
706 quick_error!(FIND_CONTEXT_IMPL
707 $name $item: $imode [$( $var:$typ ),*]
708 {$( $funcs )*});
709 )*
710 };
711 (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
712 { display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*}
713 ) => {
714 |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { write!(f, $( $exprs )*) }
715 };
716 (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
717 { display($pattern:expr) $( $tail:tt )*}
718 ) => {
719 |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) }
720 };
721 (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
722 { display($pattern:expr, $( $exprs:tt )*) $( $tail:tt )*}
723 ) => {
724 |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $( $exprs )*) }
725 };
726 (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
727 { $t:tt $( $tail:tt )*}
728 ) => {
729 quick_error!(FIND_DISPLAY_IMPL
730 $name $item: $imode
731 {$( $tail )*})
732 };
733 (FIND_DISPLAY_IMPL $name:ident $item:ident: $imode:tt
734 { }
735 ) => {
736 |self_: &$name, f: &mut ::std::fmt::Formatter| {
737 write!(f, "{}", ::std::error::Error::description(self_))
738 }
739 };
740 (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
741 [$( $var:ident ),*]
742 { description($expr:expr) $( $tail:tt )*}
743 ) => {
744 $expr
745 };
746 (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
747 [$( $var:ident ),*]
748 { $t:tt $( $tail:tt )*}
749 ) => {
750 quick_error!(FIND_DESCRIPTION_IMPL
751 $item: $imode $me $fmt [$( $var ),*]
752 {$( $tail )*})
753 };
754 (FIND_DESCRIPTION_IMPL $item:ident: $imode:tt $me:ident $fmt:ident
755 [$( $var:ident ),*]
756 { }
757 ) => {
758 stringify!($item)
759 };
760 (FIND_CAUSE_IMPL $item:ident: $imode:tt
761 [$( $var:ident ),*]
762 { cause($expr:expr) $( $tail:tt )*}
763 ) => {
764 Some($expr)
765 };
766 (FIND_CAUSE_IMPL $item:ident: $imode:tt
767 [$( $var:ident ),*]
768 { $t:tt $( $tail:tt )*}
769 ) => {
770 quick_error!(FIND_CAUSE_IMPL
771 $item: $imode [$( $var ),*]
772 { $($tail)* })
773 };
774 (FIND_CAUSE_IMPL $item:ident: $imode:tt
775 [$( $var:ident ),*]
776 { }
777 ) => {
778 None
779 };
780 (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
782 [$( $var:ident: $typ:ty ),*]
783 { from() $( $tail:tt )*}
784 ) => {
785 $(
786 impl From<$typ> for $name {
787 fn from($var: $typ) -> $name {
788 $name::$item($var)
789 }
790 }
791 )*
792 quick_error!(FIND_FROM_IMPL
793 $name $item: $imode [$( $var:$typ ),*]
794 {$( $tail )*});
795 };
796 (FIND_FROM_IMPL $name:ident $item:ident: UNIT
797 [ ]
798 { from($ftyp:ty) $( $tail:tt )*}
799 ) => {
800 impl From<$ftyp> for $name {
801 fn from(_discarded_error: $ftyp) -> $name {
802 $name::$item
803 }
804 }
805 quick_error!(FIND_FROM_IMPL
806 $name $item: UNIT [ ]
807 {$( $tail )*});
808 };
809 (FIND_FROM_IMPL $name:ident $item:ident: TUPLE
810 [$( $var:ident: $typ:ty ),*]
811 { from($fvar:ident: $ftyp:ty) -> ($( $texpr:expr ),*) $( $tail:tt )*}
812 ) => {
813 impl From<$ftyp> for $name {
814 fn from($fvar: $ftyp) -> $name {
815 $name::$item($( $texpr ),*)
816 }
817 }
818 quick_error!(FIND_FROM_IMPL
819 $name $item: TUPLE [$( $var:$typ ),*]
820 { $($tail)* });
821 };
822 (FIND_FROM_IMPL $name:ident $item:ident: STRUCT
823 [$( $var:ident: $typ:ty ),*]
824 { from($fvar:ident: $ftyp:ty) -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )*}
825 ) => {
826 impl From<$ftyp> for $name {
827 fn from($fvar: $ftyp) -> $name {
828 $name::$item {
829 $( $tvar: $texpr ),*
830 }
831 }
832 }
833 quick_error!(FIND_FROM_IMPL
834 $name $item: STRUCT [$( $var:$typ ),*]
835 { $($tail)* });
836 };
837 (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
838 [$( $var:ident: $typ:ty ),*]
839 { $t:tt $( $tail:tt )*}
840 ) => {
841 quick_error!(FIND_FROM_IMPL
842 $name $item: $imode [$( $var:$typ ),*]
843 {$( $tail )*}
844 );
845 };
846 (FIND_FROM_IMPL $name:ident $item:ident: $imode:tt
847 [$( $var:ident: $typ:ty ),*]
848 { }
849 ) => {
850 };
851 (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
853 [$( $var:ident: $typ:ty ),*]
854 { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
855 -> ($( $texpr:expr ),*) $( $tail:tt )* }
856 ) => {
857 impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
858 fn from(
859 $crate::Context($cvar, $fvar): $crate::Context<T, $ftyp>)
860 -> $name
861 {
862 $name::$item($( $texpr ),*)
863 }
864 }
865 quick_error!(FIND_CONTEXT_IMPL
866 $name $item: TUPLE [$( $var:$typ ),*]
867 { $($tail)* });
868 };
869 (FIND_CONTEXT_IMPL $name:ident $item:ident: TUPLE
870 [$( $var:ident: $typ:ty ),*]
871 { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
872 -> ($( $texpr:expr ),*) $( $tail:tt )* }
873 ) => {
874 impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
875 fn from(
876 $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
877 -> $name
878 {
879 $name::$item($( $texpr ),*)
880 }
881 }
882 quick_error!(FIND_CONTEXT_IMPL
883 $name $item: TUPLE [$( $var:$typ ),*]
884 { $($tail)* });
885 };
886 (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
887 [$( $var:ident: $typ:ty ),*]
888 { context($cvar:ident: AsRef<$ctyp:ty>, $fvar:ident: $ftyp:ty)
889 -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
890 ) => {
891 impl<T: AsRef<$ctyp>> From<$crate::Context<T, $ftyp>> for $name {
892 fn from(
893 $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
894 -> $name
895 {
896 $name::$item {
897 $( $tvar: $texpr ),*
898 }
899 }
900 }
901 quick_error!(FIND_CONTEXT_IMPL
902 $name $item: STRUCT [$( $var:$typ ),*]
903 { $($tail)* });
904 };
905 (FIND_CONTEXT_IMPL $name:ident $item:ident: STRUCT
906 [$( $var:ident: $typ:ty ),*]
907 { context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
908 -> {$( $tvar:ident: $texpr:expr ),*} $( $tail:tt )* }
909 ) => {
910 impl<'a> From<$crate::Context<$ctyp, $ftyp>> for $name {
911 fn from(
912 $crate::Context($cvar, $fvar): $crate::Context<$ctyp, $ftyp>)
913 -> $name
914 {
915 $name::$item {
916 $( $tvar: $texpr ),*
917 }
918 }
919 }
920 quick_error!(FIND_CONTEXT_IMPL
921 $name $item: STRUCT [$( $var:$typ ),*]
922 { $($tail)* });
923 };
924 (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
925 [$( $var:ident: $typ:ty ),*]
926 { $t:tt $( $tail:tt )*}
927 ) => {
928 quick_error!(FIND_CONTEXT_IMPL
929 $name $item: $imode [$( $var:$typ ),*]
930 {$( $tail )*}
931 );
932 };
933 (FIND_CONTEXT_IMPL $name:ident $item:ident: $imode:tt
934 [$( $var:ident: $typ:ty ),*]
935 { }
936 ) => {
937 };
938 (ITEM_BODY $(#[$imeta:meta])* $item:ident: UNIT
940 ) => { };
941 (ITEM_BODY $(#[$imeta:meta])* $item:ident: TUPLE
942 [$( $typ:ty ),*]
943 ) => {
944 ($( $typ ),*)
945 };
946 (ITEM_BODY $(#[$imeta:meta])* $item:ident: STRUCT
947 [$( $var:ident: $typ:ty ),*]
948 ) => {
949 {$( $var:$typ ),*}
950 };
951 (ITEM_PATTERN $name:ident $item:ident: UNIT []
952 ) => {
953 $name::$item
954 };
955 (ITEM_PATTERN $name:ident $item:ident: TUPLE
956 [$( ref $var:ident ),*]
957 ) => {
958 $name::$item ($( ref $var ),*)
959 };
960 (ITEM_PATTERN $name:ident $item:ident: STRUCT
961 [$( ref $var:ident ),*]
962 ) => {
963 $name::$item {$( ref $var ),*}
964 };
965 (ERROR_CHECK $imode:tt display($self_:tt) -> ($( $exprs:tt )*) $( $tail:tt )*)
970 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
971 (ERROR_CHECK $imode:tt display($pattern: expr) $( $tail:tt )*)
972 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
973 (ERROR_CHECK $imode:tt display($pattern: expr, $( $exprs:tt )*) $( $tail:tt )*)
974 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
975 (ERROR_CHECK $imode:tt description($expr:expr) $( $tail:tt )*)
976 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
977 (ERROR_CHECK $imode:tt cause($expr:expr) $($tail:tt)*)
978 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
979 (ERROR_CHECK $imode:tt from() $($tail:tt)*)
980 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
981 (ERROR_CHECK $imode:tt from($ftyp:ty) $($tail:tt)*)
982 => { quick_error!(ERROR_CHECK $imode $($tail)*); };
983 (ERROR_CHECK TUPLE from($fvar:ident: $ftyp:ty) -> ($( $e:expr ),*) $( $tail:tt )*)
984 => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
985 (ERROR_CHECK STRUCT from($fvar:ident: $ftyp:ty) -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
986 => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
987
988 (ERROR_CHECK TUPLE context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
989 -> ($( $e:expr ),*) $( $tail:tt )*)
990 => { quick_error!(ERROR_CHECK TUPLE $($tail)*); };
991 (ERROR_CHECK STRUCT context($cvar:ident: $ctyp:ty, $fvar:ident: $ftyp:ty)
992 -> {$( $v:ident: $e:expr ),*} $( $tail:tt )*)
993 => { quick_error!(ERROR_CHECK STRUCT $($tail)*); };
994
995 (ERROR_CHECK $imode:tt ) => {};
996 (IDENT $ident:ident) => { $ident }
998}
999
1000
1001#[derive(Debug)]
1005pub struct Context<X, E>(pub X, pub E);
1006
1007pub trait ResultExt<T, E> {
1009 fn context<X>(self, x: X) -> Result<T, Context<X, E>>;
1016}
1017
1018impl<T, E> ResultExt<T, E> for Result<T, E> {
1019 fn context<X>(self, x: X) -> Result<T, Context<X, E>> {
1020 self.map_err(|e| Context(x, e))
1021 }
1022}
1023
1024
1025
1026#[cfg(test)]
1027mod test {
1028 use std::num::{ParseFloatError, ParseIntError};
1029 use std::str::Utf8Error;
1030 use std::string::FromUtf8Error;
1031 use std::error::Error;
1032 use std::path::{Path, PathBuf};
1033
1034 use super::ResultExt;
1035
1036 quick_error! {
1037 #[derive(Debug)]
1038 pub enum Bare {
1039 One
1040 Two
1041 }
1042 }
1043
1044 #[test]
1045 fn bare_item_direct() {
1046 assert_eq!(format!("{}", Bare::One), "One".to_string());
1047 assert_eq!(format!("{:?}", Bare::One), "One".to_string());
1048 assert_eq!(Bare::One.description(), "One".to_string());
1049 assert!(Bare::One.cause().is_none());
1050 }
1051 #[test]
1052 fn bare_item_trait() {
1053 let err: &Error = &Bare::Two;
1054 assert_eq!(format!("{}", err), "Two".to_string());
1055 assert_eq!(format!("{:?}", err), "Two".to_string());
1056 assert_eq!(err.description(), "Two".to_string());
1057 assert!(err.cause().is_none());
1058 }
1059
1060 quick_error! {
1061 #[derive(Debug)]
1062 pub enum Wrapper wraps Wrapped {
1063 One
1064 Two(s: String) {
1065 display("two: {}", s)
1066 from()
1067 }
1068 }
1069 }
1070
1071 #[test]
1072 fn wrapper() {
1073 assert_eq!(format!("{}", Wrapper::from(Wrapped::One)),
1074 "One".to_string());
1075 assert_eq!(format!("{}",
1076 Wrapper::from(Wrapped::from(String::from("hello")))),
1077 "two: hello".to_string());
1078 assert_eq!(format!("{:?}", Wrapper::from(Wrapped::One)),
1079 "Wrapper(One)".to_string());
1080 assert_eq!(Wrapper::from(Wrapped::One).description(),
1081 "One".to_string());
1082 }
1083
1084 quick_error! {
1085 #[derive(Debug, PartialEq)]
1086 pub enum TupleWrapper {
1087 ParseFloatError(err: ParseFloatError) {
1089 from()
1090 description(err.description())
1091 display("parse float error: {err}", err=err)
1092 cause(err)
1093 }
1094 Other(descr: &'static str) {
1095 description(descr)
1096 display("Error: {}", descr)
1097 }
1098 FromUtf8Error(err: Utf8Error, source: Vec<u8>) {
1100 cause(err)
1101 display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
1102 description("utf8 error")
1103 from(err: FromUtf8Error) -> (err.utf8_error().clone(), err.into_bytes())
1104 }
1105 Discard {
1106 from(&'static str)
1107 }
1108 Singleton {
1109 display("Just a string")
1110 }
1111 }
1112 }
1113
1114 #[test]
1115 fn tuple_wrapper_err() {
1116 let cause = "one and a half times pi".parse::<f32>().unwrap_err();
1117 let err = TupleWrapper::ParseFloatError(cause.clone());
1118 assert_eq!(format!("{}", err), format!("parse float error: {}", cause));
1119 assert_eq!(format!("{:?}", err), format!("ParseFloatError({:?})", cause));
1120 assert_eq!(err.description(), cause.description());
1121 assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
1122 }
1123
1124 #[test]
1125 fn tuple_wrapper_trait_str() {
1126 let desc = "hello";
1127 let err: &Error = &TupleWrapper::Other(desc);
1128 assert_eq!(format!("{}", err), format!("Error: {}", desc));
1129 assert_eq!(format!("{:?}", err), format!("Other({:?})", desc));
1130 assert_eq!(err.description(), desc);
1131 assert!(err.cause().is_none());
1132 }
1133
1134 #[test]
1135 fn tuple_wrapper_trait_two_fields() {
1136 let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1137 let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
1138 let err: &Error = &TupleWrapper::FromUtf8Error(cause.clone(), invalid_utf8.clone());
1139 assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
1140 assert_eq!(format!("{:?}", err), format!("FromUtf8Error({:?}, {:?})", cause, invalid_utf8));
1141 assert_eq!(err.description(), "utf8 error");
1142 assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
1143 }
1144
1145 #[test]
1146 fn tuple_wrapper_from() {
1147 let cause = "one and a half times pi".parse::<f32>().unwrap_err();
1148 let err = TupleWrapper::ParseFloatError(cause.clone());
1149 let err_from: TupleWrapper = From::from(cause);
1150 assert_eq!(err_from, err);
1151 }
1152
1153 #[test]
1154 fn tuple_wrapper_custom_from() {
1155 let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1156 let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err();
1157 let err = TupleWrapper::FromUtf8Error(cause.utf8_error().clone(), invalid_utf8);
1158 let err_from: TupleWrapper = From::from(cause);
1159 assert_eq!(err_from, err);
1160 }
1161
1162 #[test]
1163 fn tuple_wrapper_discard() {
1164 let err: TupleWrapper = From::from("hello");
1165 assert_eq!(format!("{}", err), format!("Discard"));
1166 assert_eq!(format!("{:?}", err), format!("Discard"));
1167 assert_eq!(err.description(), "Discard");
1168 assert!(err.cause().is_none());
1169 }
1170
1171 #[test]
1172 fn tuple_wrapper_singleton() {
1173 let err: TupleWrapper = TupleWrapper::Singleton;
1174 assert_eq!(format!("{}", err), format!("Just a string"));
1175 assert_eq!(format!("{:?}", err), format!("Singleton"));
1176 assert_eq!(err.description(), "Singleton");
1177 assert!(err.cause().is_none());
1178 }
1179
1180 quick_error! {
1181 #[derive(Debug, PartialEq)]
1182 pub enum StructWrapper {
1183 Utf8Error{ err: Utf8Error, hint: Option<&'static str> } {
1185 cause(err)
1186 display(me) -> ("{desc} at index {pos}: {err}", desc=me.description(), pos=err.valid_up_to(), err=err)
1187 description("utf8 error")
1188 from(err: Utf8Error) -> { err: err, hint: None }
1189 }
1190 ExcessComma { descr: &'static str, } {
1192 description(descr)
1193 display("Error: {}", descr)
1194 }
1195 }
1196 }
1197
1198 #[test]
1199 fn struct_wrapper_err() {
1200 let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1201 let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
1202 let err: &Error = &StructWrapper::Utf8Error{ err: cause.clone(), hint: Some("nonsense") };
1203 assert_eq!(format!("{}", err), format!("{desc} at index {pos}: {cause}", desc=err.description(), pos=cause.valid_up_to(), cause=cause));
1204 assert_eq!(format!("{:?}", err), format!("Utf8Error {{ err: {:?}, hint: {:?} }}", cause, Some("nonsense")));
1205 assert_eq!(err.description(), "utf8 error");
1206 assert_eq!(format!("{:?}", err.cause().unwrap()), format!("{:?}", cause));
1207 }
1208
1209 #[test]
1210 fn struct_wrapper_struct_from() {
1211 let invalid_utf8: Vec<u8> = vec![0, 159, 146, 150];
1212 let cause = String::from_utf8(invalid_utf8.clone()).unwrap_err().utf8_error();
1213 let err = StructWrapper::Utf8Error{ err: cause.clone(), hint: None };
1214 let err_from: StructWrapper = From::from(cause);
1215 assert_eq!(err_from, err);
1216 }
1217
1218 #[test]
1219 fn struct_wrapper_excess_comma() {
1220 let descr = "hello";
1221 let err = StructWrapper::ExcessComma { descr: descr };
1222 assert_eq!(format!("{}", err), format!("Error: {}", descr));
1223 assert_eq!(format!("{:?}", err), format!("ExcessComma {{ descr: {:?} }}", descr));
1224 assert_eq!(err.description(), descr);
1225 assert!(err.cause().is_none());
1226 }
1227
1228 quick_error! {
1229 #[derive(Debug)]
1230 pub enum ContextErr {
1231 Float(src: String, err: ParseFloatError) {
1232 context(s: &'a str, e: ParseFloatError) -> (s.to_string(), e)
1233 display("Float error {:?}: {}", src, err)
1234 }
1235 Int { src: String, err: ParseIntError } {
1236 context(s: &'a str, e: ParseIntError)
1237 -> {src: s.to_string(), err: e}
1238 display("Int error {:?}: {}", src, err)
1239 }
1240 Utf8(path: PathBuf, err: Utf8Error) {
1241 context(p: AsRef<Path>, e: Utf8Error)
1242 -> (p.as_ref().to_path_buf(), e)
1243 display("Path error at {:?}: {}", path, err)
1244 }
1245 Utf8Str(s: String, err: ::std::io::Error) {
1246 context(s: AsRef<str>, e: ::std::io::Error)
1247 -> (s.as_ref().to_string(), e)
1248 display("Str error {:?}: {}", s, err)
1249 }
1250 }
1251 }
1252
1253 #[test]
1254 fn parse_float_error() {
1255 fn parse_float(s: &str) -> Result<f32, ContextErr> {
1256 Ok(try!(s.parse().context(s)))
1257 }
1258 assert_eq!(format!("{}", parse_float("12ab").unwrap_err()),
1259 r#"Float error "12ab": invalid float literal"#);
1260 }
1261
1262 #[test]
1263 fn parse_int_error() {
1264 fn parse_int(s: &str) -> Result<i32, ContextErr> {
1265 Ok(try!(s.parse().context(s)))
1266 }
1267 assert_eq!(format!("{}", parse_int("12.5").unwrap_err()),
1268 r#"Int error "12.5": invalid digit found in string"#);
1269 }
1270
1271 #[test]
1272 fn debug_context() {
1273 fn parse_int(s: &str) -> i32 {
1274 s.parse().context(s).unwrap()
1275 }
1276 assert_eq!(parse_int("12"), 12);
1277 assert_eq!(format!("{:?}", "x".parse::<i32>().context("x")),
1278 r#"Err(Context("x", ParseIntError { kind: InvalidDigit }))"#);
1279 }
1280
1281 #[test]
1282 fn path_context() {
1283 fn parse_utf<P: AsRef<Path>>(s: &[u8], p: P)
1284 -> Result<(), ContextErr>
1285 {
1286 try!(::std::str::from_utf8(s).context(p));
1287 Ok(())
1288 }
1289 let etext = parse_utf(b"a\x80\x80", "/etc").unwrap_err().to_string();
1290 assert!(etext.starts_with(
1291 "Path error at \"/etc\": invalid utf-8"));
1292 let etext = parse_utf(b"\x80\x80", PathBuf::from("/tmp")).unwrap_err()
1293 .to_string();
1294 assert!(etext.starts_with(
1295 "Path error at \"/tmp\": invalid utf-8"));
1296 }
1297
1298 #[test]
1299 fn conditional_compilation() {
1300 quick_error! {
1301 #[allow(dead_code)]
1302 #[derive(Debug)]
1303 pub enum Test {
1304 #[cfg(feature = "foo")]
1305 Variant
1306 }
1307 }
1308 }
1309}