#[doc(hidden)]
#[macro_export]
macro_rules! error_type_as_item {
($i:item) => {$i};
}
#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body_emit {
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident
) => {
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
disp ()
$($tail:tt)*
) => {
impl<'a> $edi_tr for (&'a $err_name, &'a $var_ty) {
fn error_fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(self.1, fmt)
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
disp (($disp_arg:ident, $disp_fmt:ident) $disp_expr:expr)
$($tail:tt)*
) => {
impl<'a> $edi_tr for (&'a $err_name, &'a $var_ty) {
fn error_fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
let $disp_arg = self.1;
let $disp_fmt = fmt;
$disp_expr
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
desc ()
$($tail:tt)*
) => {
impl<'a> $ede_tr<'a> for (&'a $err_name, &'a $var_ty) {
fn error_desc(&self) -> &'a str {
::std::error::Error::description(self.1)
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
desc (($desc_arg:ident) $desc_expr:expr)
$($tail:tt)*
) => {
impl<'a> $ede_tr<'a> for (&'a $err_name, &'a $var_ty) {
fn error_desc(&self) -> &'a str {
let $desc_arg = self.1;
$desc_expr
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
cause ()
$($tail:tt)*
) => {
impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
fn error_cause(&self) -> ::std::option::Option<&'a ::std::error::Error> {
None
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
cause (($cl_arg:ident) $cl_expr:expr)
$($tail:tt)*
) => {
impl<'a> $ec_tr<'a> for (&'a $err_name, &'a $var_ty) {
fn error_cause(&self) -> ::std::option::Option<&'a ::std::error::Error> {
let $cl_arg = self.1;
$cl_expr
}
}
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
from ($(($cl_arg:ident: $cl_ty:ty) $cl_expr:expr);*)
$($tail:tt)*
) => {
$(
impl ::std::convert::From<$cl_ty> for $err_name {
fn from($cl_arg: $cl_ty) -> $err_name {
$err_name::$var_name($cl_expr)
}
}
)*
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr $($tail)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! error_type_var_body {
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, $from:tt; {}
) => {
error_type_var_body_emit! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
disp $disp, desc $desc, cause $cause, from $from
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, $from:tt; {
disp ($cl_arg:ident, $cl_fmt:ident) $cl_body:expr;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
(($cl_arg, $cl_fmt) $cl_body), $desc, $cause, $from;
{$($tail)*}
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, $from:tt; {
desc ($cl_arg:ident) $cl_body:expr;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
$disp, (($cl_arg) $cl_body), $cause, $from;
{$($tail)*}
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, $from:tt; {
cause ($cl_arg:ident) $cl_body:expr;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
$disp, $desc, (($cl_arg) $cl_body), $from;
{$($tail)*}
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, $from:tt; {
cause;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
$disp, $desc, ((e) ::std::error::Error::cause(e)), $from;
{$($tail)*}
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, (); {
from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
$disp, $desc, $cause, (($cl_arg: $cl_ty) $cl_body);
{$($tail)*}
}
};
(
$err_name:ident, $var_name:ident, $var_ty:ty, $edi_tr:ident, $ede_tr:ident, $ec_tr:ident,
$disp:tt, $desc:tt, $cause:tt, ($($from:tt)*); {
from ($cl_arg:ident: $cl_ty:ty) $cl_body:expr;
$($tail:tt)*
}
) => {
error_type_var_body! {
$err_name, $var_name, $var_ty, $edi_tr, $ede_tr, $ec_tr,
$disp, $desc, $cause, (($cl_arg: $cl_ty) $cl_body; $($from)*);
{$($tail)*}
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! error_type_impl {
(
$(#[$($derive_tts:tt)*])*
enum $err_name:ident {
$($var_name:ident($var_ty:ty) $var_body:tt),+
$(,)*
}
) => {
$(
impl ::std::convert::From<$var_ty> for $err_name {
fn from(value: $var_ty) -> $err_name {
$err_name::$var_name(value)
}
}
)+
impl ::std::fmt::Display for $err_name {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
match *self {
$(
$err_name::$var_name(ref v) => (self, v).error_fmt(fmt)
),+
}
}
}
pub trait ErrorDisplay {
fn error_fmt(&self, &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error>;
}
pub trait ErrorDescription<'a> {
fn error_desc(&self) -> &'a str;
}
pub trait ErrorCause<'a> {
fn error_cause(&self) -> ::std::option::Option<&'a ::std::error::Error>;
}
impl ::std::error::Error for $err_name {
fn description(&self) -> &str {
use self::ErrorDescription;
match *self {
$(
$err_name::$var_name(ref v) => (self, v).error_desc()
),+
}
}
fn cause(&self) -> ::std::option::Option<&::std::error::Error> {
use self::ErrorCause;
match *self {
$(
$err_name::$var_name(ref v) => (self, v).error_cause()
),+
}
}
}
$(
error_type_var_body! {
$err_name, $var_name, $var_ty,
ErrorDisplay, ErrorDescription, ErrorCause,
(), (), (), ();
$var_body
}
)+
};
}
#[macro_export]
macro_rules! error_type {
(
$(#[$($derive_tts:tt)*])*
pub enum $err_name:ident {
$($var_name:ident($var_ty:ty) $var_body:tt),+
$(,)*
}
) => {
error_type_as_item! {
$(#[$($derive_tts)*])*
pub enum $err_name {
$($var_name($var_ty)),+
}
}
error_type_impl! {
$(#[$($derive_tts)*])*
enum $err_name {
$($var_name($var_ty) $var_body),+
}
}
};
(
$(#[$($derive_tts:tt)*])*
enum $err_name:ident {
$($var_name:ident($var_ty:ty) $var_body:tt),+
$(,)*
}
) => {
error_type_as_item! {
$(#[$($derive_tts)*])*
enum $err_name {
$($var_name($var_ty)),+
}
}
error_type_impl! {
$(#[$($derive_tts)*])*
enum $err_name {
$($var_name($var_ty) $var_body),+
}
}
};
}