#[macro_export]
#[doc(hidden)]
macro_rules! __build_method {
($(#[$attr:meta])* $($method_def:ident)+; {$($self_ref:tt)*}; $self_:ident; { $($arg:ident: $arg_ty:ty),* }; $( -> $return_type:ty)?; [$($(#[$var_attr:meta])* $variant:ident),+]; $enum_name:ident) => {
$(#[$attr])* $($method_def)+($($self_ref)* $self_, $($arg: $arg_ty),*) $( -> $return_type)? {
$crate::__build_method!(@make_match $self_; $($method_def)+; $enum_name; [$($(#[$var_attr])* $variant),+]; ($($arg),*))
}
};
(@make_match $self_:ident; fn $method:ident; $enum_name:ident; [$($(#[$var_attr:meta])* $variant:ident),+]; $args:tt) => {
match $self_ {
$(
$(#[$var_attr])*
$enum_name::$variant(v) => v.$method $args
),+
}
};
(@make_match $self_:ident; async fn $method:ident; $enum_name:ident; [$($(#[$var_attr:meta])* $variant:ident),+]; $args:tt) => {
match $self_ {
$(
$(#[$var_attr])*
$enum_name::$variant(v) => v.$method $args .await
),+
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __munch_methods {
({ }; [$($(#[$var_attr:meta])* $variant:ident),+]; $enum_name:ident) => {};
({ $(#[$attr:meta])* $($method_def:ident)+($self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)?; $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+(&$self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)?; $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { & }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+(&mut $self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)?; $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { &mut }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+($self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)? $body:block $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+(&$self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)? $body:block $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { & }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+(&mut $self_:ident $(, $($arg:ident: $arg_ty:ty),*)? $(,)?) $( -> $return_type:ty)? $body:block $($rest:tt)* }; $variants:tt; $enum_name:ident) => {
$crate::__build_method!($(#[$attr])* $($method_def)+; { &mut }; $self_; { $($($arg: $arg_ty),*)? }; $( -> $return_type)?; $variants; $enum_name);
$crate::__munch_methods!({ $($rest)* }; $variants; $enum_name);
};
({ $(#[$attr:meta])* $($method_def:ident)+($($args:tt)*) $($rest:tt)* }; [$($(#[$var_attr:meta])* $variant:ident),+]; $enum_name:ident ) => {
compile_error!(concat!("method `", stringify!($($method_def)+), "` should receive self"));
}
}
#[macro_export]
macro_rules! enum_dispatch {
(
$(#[$trait_attr:meta])*
$trait_vis:vis trait $train_name:ident $(: $lf:lifetime)? $(: $super_trait1:ident $(::$super_trait2:ident)* $(+ $super_trait3:ident $(::$super_trait4:ident)*)*)? $(+ $lf2:lifetime)? {
$($any:tt)*
}
$(#[$enum_attr:meta])*
$enum_vis:vis enum $enum_name:ident {
$($(#[$var_attr:meta])* $variant:ident($variant_type:ty)),+$(,)?
}
) => {
$(#[$trait_attr])*
$trait_vis trait $train_name $(: $lf)? $(: $super_trait1 $(::$super_trait2)* $(+ $super_trait3 $(::$super_trait4)*)*)? $(+ $lf2)? {
$($any)*
}
$(#[$enum_attr])*
$enum_vis enum $enum_name {
$($(#[$var_attr])* $variant($variant_type)),+
}
impl $train_name for $enum_name {
$crate::__munch_methods!({ $($any)* }; [$($(#[$var_attr])* $variant),+]; $enum_name);
}
$(
$(#[$var_attr])*
impl From<$variant_type> for $enum_name {
fn from(value: $variant_type) -> $enum_name {
$enum_name::$variant(value)
}
}
)+
};
}