lib::quick_error! [] [src]

macro_rules! quick_error {
    (   $(#[$meta:meta])*
        pub enum $name:ident { $($chunks:tt)* }
    ) => {
        quick_error!(SORT [pub enum $name $(#[$meta])* ]
            enum [] items [] buf []
            queue [ $($chunks)* ]);
    };
    (   $(#[$meta:meta])*
        enum $name:ident { $($chunks:tt)* }
    ) => {
        quick_error!(SORT [enum $name $(#[$meta])* ]
            enum [] items [] buf []
            queue [ $($chunks)* ]);
    };
/*
macro_rules! sort {
    ({ $( $(#[$meta:meta])* => $item:ident )* }
     { $(#[$bufmeta:meta])* }
     { #[$nextmeta:meta] $($tail:tt)* }) => {
     sort!({ $( $(#[$meta])* => $item )* } { $(#[$bufmeta])* #[$nextmeta] } { $($tail)* });
    };
    ({ $( $(#[$meta:meta])* => $item:ident )* }
     { $(#[$bufmeta:meta])* }
     { $name:ident $($tail:tt)* }) => {
     sort!({ $( $(#[$meta])* => $item )* $(#[$bufmeta])* => $name } {} { $($tail)* });
    };
    ({ $( $(#[$meta:meta])* => $item:ident )* } {} {}) => {
        #[derive(Debug)]
        pub enum Test {
            $(
                $(#[$meta])*
                $item,
            )*
        }
    };
}
*/

    // Queue is empty, can do the work
    (SORT [enum $name:ident $(#[$meta:meta])* ]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $( ( $($etyp:ty),* ) )* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ ]
        queue [ ]
    ) => {
        $(#[$meta])*
        enum $name {
           $(
               $(#[$emeta])*
               $eitem $(( $($etyp),* ))*,
           )*
        }
        quick_error!(IMPLEMENTATIONS $name { $(
           $iitem $(( $($ivar: $ityp),* ))* { $($ifuncs)* }
           )* });
        $(
            quick_error!(ERROR_CHECK $($ifuncs)*);
        )*
    };
    (SORT [pub enum $name:ident $(#[$meta:meta])* ]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $( ( $($etyp:ty),* ) )* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ ]
        queue [ ]
    ) => {
        $(#[$meta])*
        pub enum $name {
           $(
               $(#[$emeta])*
               $eitem $(( $($etyp),* ))*,
           )*
        }
        quick_error!(IMPLEMENTATIONS $name { $(
           $iitem $(( $($ivar: $ityp),* ))* { $($ifuncs)* }
           )* });
        $(
            quick_error!(ERROR_CHECK $($ifuncs)*);
        )*
    };
    // Add meta to buffer
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )* ]
        queue [ #[$qmeta:meta] $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )* ]
            buf [ $( #[$bmeta] )* #[$qmeta] ]
            queue [ $($tail)* ]);
    };
    // Add ident to buffer
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )* ]
        queue [ $qitem:ident $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [ $( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )* ]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )* ]
            buf [ $(#[$bmeta])* => $qitem ]
            queue [ $($tail)* ]);
    };
    // Flush buffer on meta after ident
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )*
            => $bitem:ident $(( $($bvar:ident : $btyp:ty),* ))* ]
        queue [ #[$qmeta:meta] $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
                     $(#[$bmeta])* => $bitem $(( $($btyp),* ))*]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )*
                     $bitem $(( $($bvar:$btyp),* ))* {} ]
            buf [ #[$qmeta] ]
            queue [ $($tail)* ]);
    };
    // Add parenthesis
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )* => $bitem:ident ]
        queue [ ( $( $qvar:ident : $qtyp:ty ),* ) $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )* ]
            buf [ $( #[$bmeta] )* => $bitem ( $( $qvar:$qtyp ),* ) ]
            queue [ $($tail)* ]);
    };
    // Add braces and flush always on braces
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )*
                 => $bitem:ident $(( $($bvar:ident : $btyp:ty),* ))* ]
        queue [ { $($qfuncs:tt)* } $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
                     $(#[$bmeta])* => $bitem $(( $($btyp),* ))* ]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )*
                     $bitem $(( $($bvar:$btyp),* ))* { $($qfuncs)* } ]
            buf [ ]
            queue [ $($tail)* ]);
    };
    // Flush buffer on double ident
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )*
                 => $bitem:ident $(( $($bvar:ident : $btyp:ty),* ))* ]
        queue [ $qitem:ident $($tail:tt)* ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
                     $(#[$bmeta])* => $bitem $(( $($btyp),* ))*]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )*
                     $bitem $(( $($bvar:$btyp),* ))* {} ]
            buf [ => $qitem ]
            queue [ $($tail)* ]);
    };
    // Flush buffer on end
    (SORT [$($def:tt)*]
        enum [ $( $(#[$emeta:meta])*
                  => $eitem:ident $(( $($etyp:ty),* ))* )* ]
        items [ $( $iitem:ident $(( $($ivar:ident : $ityp:ty),* ))*
                                { $($ifuncs:tt)* } )* ]
        buf [ $( #[$bmeta:meta] )*
            => $bitem:ident $(( $($bvar:ident : $btyp:ty),* ))* ]
        queue [ ]
    ) => {
        quick_error!(SORT [$($def)* ]
            enum [$( $(#[$emeta])* => $eitem $(( $($etyp),* ))* )*
                     $(#[$bmeta])* => $bitem $(( $($btyp),* ))* ]
            items [ $( $iitem $(( $($ivar:$ityp),* ))* { $($ifuncs)* } )*
                     $bitem $(( $($bvar:$btyp),* ))* {} ]
            buf [ ]
            queue [ ]);
    };
    (IMPLEMENTATIONS
        $name:ident {
            $(
                $item:ident $( ( $($var:ident : $typ:ty),* ) )* { $($funcs:tt)* }
            )*
        }
    ) => {
        #[allow(unused)]
        impl ::std::fmt::Display for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                -> ::std::fmt::Result
            {
                match self {
                    $(
                        &$name::$item $( ( $(ref $var),* ) )* => {
                            quick_error!(FIND_DISPLAY_IMPL
                                $item self fmt [ $( ( $($var)* ) )* ]
                                { $($funcs)* })
                        }
                    )*
                }
            }
        }
        #[allow(unused)]
        impl ::std::error::Error for $name {
            fn description(&self) -> &str {
                match self {
                    $(
                        &$name::$item $( ( $(ref $var),* ) )* => {
                            quick_error!(FIND_DESCRIPTION_IMPL
                                $item self fmt [ $( ( $($var)* ) )* ]
                                { $($funcs)* })
                        }
                    )*
                }
            }
            fn cause(&self) -> Option<&::std::error::Error> {
                match self {
                    $(
                        &$name::$item $( ( $(ref $var),* ) )* => {
                            quick_error!(FIND_CAUSE_IMPL
                                $item [ $( ( $($var)* ) )* ]
                                { $($funcs)* })
                        }
                    )*
                }
            }
        }
        $(
            quick_error!(FIND_FROM_IMPL
                $name $item [ $( ( $($var:$typ)* ) )* ]
                { $($funcs)* });
        )*
    };
    (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { display($($exprs:expr),*) $($tail:tt)* }
    ) => {
        write!($fmt, $($exprs),*)
    };
    (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { $t:tt $($tail:tt)* }
    ) => {
        quick_error!(FIND_DISPLAY_IMPL
            $item $me $fmt [ $( ( $($var)* ) )* ]
            { $($tail)* })
    };
    (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { }
    ) => {
        write!($fmt, "{}", ::std::error::Error::description($me))
    };
    (FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { description($expr:expr) $($tail:tt)* }
    ) => {
        $expr
    };
    (FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { $t:tt $($tail:tt)* }
    ) => {
        quick_error!(FIND_DESCRIPTION_IMPL
            $item $me $fmt [ $( ( $($var)* ) )* ]
            { $($tail)* })
    };
    (FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident
        [ $( ( $($var:ident)* ) )* ]
        { }
    ) => {
        stringify!($item)
    };
    (FIND_CAUSE_IMPL $item:ident
        [ $( ( $($var:ident)* ) )* ]
        { cause($expr:expr) $($tail:tt)* }
    ) => {
        Some($expr)
    };
    (FIND_CAUSE_IMPL $item:ident
        [ $( ( $($var:ident)* ) )* ]
        { $t:tt $($tail:tt)* }
    ) => {
        quick_error!(FIND_CAUSE_IMPL
            $item [ $( ( $($var)* ) )* ]
            { $($tail)* })
    };
    (FIND_CAUSE_IMPL $item:ident
        [ $( ( $($var:ident)* ) )* ]
        { }
    ) => {
        None
    };
    (FIND_FROM_IMPL $name:ident $item:ident
        [ $( ( $($var:ident : $typ:ty)* ) )* ]
        { from() $($tail:tt)* }
    ) => {
        $( $(
            impl From<$typ> for $name {
                fn from($var: $typ) -> $name {
                    $name::$item($var)
                }
            }
        )* )*
        quick_error!(FIND_FROM_IMPL
            $name $item [ $( ( $($var:$typ)* ) )* ]
            { $($tail)* });
    };
    (FIND_FROM_IMPL $name:ident $item:ident
        [ ]
        { from($ftyp:ty) $($tail:tt)* }
    ) => {
        impl From<$ftyp> for $name {
            fn from(_discarded_error: $ftyp) -> $name {
                $name::$item
            }
        }
        quick_error!(FIND_FROM_IMPL
            $name $item [  ]
            { $($tail)* });
    };
    (FIND_FROM_IMPL $name:ident $item:ident
        [ $( ( $($var:ident : $typ:ty)* ) )* ]
        { from($fvar:ident : $ftyp:ty) -> ($($expr:expr),*) $($tail:tt)* }
    ) => {
        impl From<$ftyp> for $name {
            fn from($fvar: $ftyp) -> $name {
                $name::$item($($expr),*)
            }
        }
        quick_error!(FIND_FROM_IMPL
            $name $item [ $( ( $($var:$typ)* ) )* ]
            { $($tail)* });
    };
    (FIND_FROM_IMPL $name:ident $item:ident
        [ $( ( $($var:ident : $typ:ty)* ) )* ]
        { $t:tt $($tail:tt)* }
    ) => {
        quick_error!(FIND_FROM_IMPL
            $name $item[ $( ( $($var:$typ)* ) )* ]
            { $($tail)* });
    };
    (FIND_FROM_IMPL $name:ident $item:ident
        [ $( ( $($var:ident : $typ:ty)* ) )* ]
        { }
    ) => {
    };
    // This one should match all allowed sequences in "funcs" but not match
    // anything else.
    // This is to contrast FIND_* clauses which just find stuff they need and
    // skip everything else completely
    (ERROR_CHECK display($($exprs:expr),*) $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK description($expr:expr) $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK cause($expr:expr) $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK from() $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK from($ftyp:ty) $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK from($fvar:ident : $ftyp:ty) -> ($($e:expr),*) $($tail:tt)*)
    => { quick_error!(ERROR_CHECK $($tail)*); };
    (ERROR_CHECK) => {};
}

Main macro that does all the work