#![deny(warnings)]
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
extern crate core;
#[doc(hidden)]
pub use core::iter::Iterator as std_iter_Iterator;
#[doc(hidden)]
pub use core::option::Option as std_option_Option;
#[doc(hidden)]
pub use core::iter::ExactSizeIterator as std_iter_ExactSizeIterator;
#[doc(hidden)]
pub use core::fmt::Display as std_fmt_Display;
#[doc(hidden)]
pub use core::fmt::Formatter as std_fmt_Formatter;
#[doc(hidden)]
pub use core::fmt::Result as std_fmt_Result;
#[doc(hidden)]
pub use core::result::Result as std_result_Result;
#[doc(hidden)]
pub use core::str::FromStr as std_str_FromStr;
#[doc(hidden)]
pub use core::mem::replace as std_mem_replace;
#[doc(hidden)]
pub use core::convert::From as std_convert_From;
#[doc(hidden)]
#[macro_export]
macro_rules! enum_derive_util {
(@as_expr $e:expr) => {$e};
(@as_item $($i:item)+) => {$($i)+};
(@first_expr $head:expr $(, $($($tail:expr),+ $(,)?)?)?) => {$head};
(
@collect_unitary_variants ($callback:ident { $($args:tt)* }),
($(,)*) -> ($($var_names:ident,)*)
) => {
$crate::enum_derive_util! {
@as_item
$callback!{ $($args)* ($($var_names),*) }
}
};
(
@collect_unitary_variants $fixed:tt,
(#[$_attr:meta] $($tail:tt)*) -> ($($var_names:tt)*)
) => {
$crate::enum_derive_util! {
@collect_unitary_variants $fixed,
($($tail)*) -> ($($var_names)*)
}
};
(
@collect_unitary_variants $fixed:tt,
($var:ident $(= $_val:expr)*, $($tail:tt)*) -> ($($var_names:tt)*)
) => {
$crate::enum_derive_util! {
@collect_unitary_variants $fixed,
($($tail)*) -> ($($var_names)* $var,)
}
};
(
@collect_unitary_variants ($name:ident),
($var:ident $_struct:tt, $($tail:tt)*) -> ($($var_names:tt)*)
) => {
const _error: () = "cannot parse unitary variants from enum with non-unitary variants";
};
(
@collect_unary_variants ($callback:ident { $($args:tt)* }),
($(,)*) -> ($($out:tt)*)
) => {
$crate::enum_derive_util! {
@as_item
$callback!{ $($args)* ($($out)*) }
}
};
(
@collect_unary_variants $fixed:tt,
(#[$_attr:meta] $($tail:tt)*) -> ($($out:tt)*)
) => {
$crate::enum_derive_util! {
@collect_unary_variants $fixed,
($($tail)*) -> ($($out)*)
}
};
(
@collect_unary_variants $fixed:tt,
($var_name:ident($vis:vis $var_ty:ty), $($tail:tt)*) -> ($($out:tt)*)
) => {
$crate::enum_derive_util! {
@collect_unary_variants $fixed,
($($tail)*) -> ($($out)* $var_name($var_ty),)
}
};
(
@collect_unary_variants ($name:ident),
($var:ident $_struct:tt, $($tail:tt)*) -> ($($_out:tt)*)
) => {
const _error: () = "cannot parse unary variants from enum with non-unary tuple variants";
};
}
#[macro_export]
macro_rules! IterVariants {
(($itername:ident) $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(IterVariants { @expand ($vis) $itername, $name }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis) $itername:ident, $name:ident ()
) => {
$crate::enum_derive_util! { @as_item $vis struct $itername; }
impl $crate::std_iter_Iterator for $itername {
type Item = $name;
fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
None
}
fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
(0, Some(0))
}
}
impl $crate::std_iter_ExactSizeIterator for $itername { }
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn iter_variants() -> $itername {
$itername
}
}
}
};
(
@expand ($vis:vis) $itername:ident, $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! { @as_item $vis struct $itername($crate::std_option_Option<$name>); }
$crate::IterVariants! { @iter ($itername, $name), ($($var_names,)*) -> () () (0usize) }
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn iter_variants() -> $itername {
$itername($crate::std_option_Option::Some($crate::enum_derive_util!(@first_expr $($name::$var_names),+)))
}
}
}
};
(
@iter ($itername:ident, $name:ident), () -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_iter_Iterator for $itername {
type Item = $name;
fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
let next_item = match self.0 {
$($next_body)*
$crate::std_option_Option::None => $crate::std_option_Option::None
};
$crate::std_mem_replace(&mut self.0, next_item)
}
fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
let variants = $($count)*;
let progress = match self.0 {
$($size_body)*
$crate::std_option_Option::None => variants
};
(variants - progress, $crate::std_option_Option::Some(variants - progress))
}
}
impl $crate::std_iter_ExactSizeIterator for $itername { }
}
};
(
@iter ($itername:ident, $name:ident), ($a:ident, $b:ident, $($rest:tt)*) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::IterVariants! {
@iter ($itername, $name), ($b, $($rest)*)
-> (
$($next_body)*
$crate::std_option_Option::Some($name::$a) => $crate::std_option_Option::Some($name::$b),
)
(
$($size_body)*
$crate::std_option_Option::Some($name::$a) => $($count)*,
)
($($count)* + 1usize)
}
};
(
@iter ($itername:ident, $name:ident), ($a:ident,) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::IterVariants! {
@iter ($itername, $name), ()
-> (
$($next_body)*
$crate::std_option_Option::Some($name::$a) => $crate::std_option_Option::None,
)
(
$($size_body)*
$crate::std_option_Option::Some($name::$a) => $($count)*,
)
($($count)* + 1usize)
}
};
}
#[macro_export]
macro_rules! IterVariantNames {
(($itername:ident) $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(IterVariantNames { @expand ($vis) $itername, $name }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis) $itername:ident, $name:ident ()
) => {
$crate::enum_derive_util! { @as_item $vis struct $itername; }
impl $crate::std_iter_Iterator for $itername {
type Item = &'static str;
fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
$crate::std_option_Option::None
}
fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
(0, $crate::std_option_Option::Some(0))
}
}
impl $crate::std_iter_ExactSizeIterator for $itername { }
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn iter_variant_names() -> $itername {
$itername
}
}
}
};
(
@expand ($vis:vis) $itername:ident, $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! { @as_item $vis struct $itername($crate::std_option_Option<$name>); }
$crate::IterVariantNames! { @iter ($itername, $name), ($($var_names,)*) -> () () (0usize) }
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn iter_variant_names() -> $itername {
$itername($crate::std_option_Option::Some($crate::enum_derive_util!(@first_expr $($name::$var_names),+)))
}
}
}
};
(
@iter ($itername:ident, $name:ident), () -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_iter_Iterator for $itername {
type Item = &'static str;
fn next(&mut self) -> $crate::std_option_Option<Self::Item> {
let (next_state, result) = match self.0 {
$($next_body)*
$crate::std_option_Option::None => ($crate::std_option_Option::None, $crate::std_option_Option::None)
};
self.0 = next_state;
result
}
fn size_hint(&self) -> (usize, $crate::std_option_Option<usize>) {
let variants = $($count)*;
let progress = match self.0 {
$($size_body)*
None => variants
};
(variants - progress, $crate::std_option_Option::Some(variants - progress))
}
}
impl $crate::std_iter_ExactSizeIterator for $itername { }
}
};
(
@iter ($itername:ident, $name:ident), ($a:ident, $b:ident, $($rest:tt)*) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::IterVariantNames! {
@iter ($itername, $name), ($b, $($rest)*)
-> (
$($next_body)*
$crate::std_option_Option::Some($name::$a)
=> ($crate::std_option_Option::Some($name::$b), $crate::std_option_Option::Some(stringify!($a))),
)
(
$($size_body)*
$crate::std_option_Option::Some($name::$a) => $($count)*,
)
($($count)* + 1usize)
}
};
(
@iter ($itername:ident, $name:ident), ($a:ident,) -> ($($next_body:tt)*) ($($size_body:tt)*) ($($count:tt)*)
) => {
$crate::IterVariantNames! {
@iter ($itername, $name), ()
-> (
$($next_body)*
$crate::std_option_Option::Some($name::$a)
=> ($crate::std_option_Option::None, $crate::std_option_Option::Some(stringify!($a))),
)
(
$($size_body)*
$crate::std_option_Option::Some($name::$a) => $($count)*,
)
($($count)* + 1usize)
}
};
}
#[macro_export]
macro_rules! NextVariant {
(() $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(NextVariant { @expand ($vis) $name }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis) $name:ident ()
) => {
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn next_variant(&self) -> $crate::std_option_Option<$name> {
loop {}
}
}
}
};
(
@expand ($vis:vis) $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn next_variant(&self) -> $crate::std_option_Option<$name> {
$crate::NextVariant!(@arms ($name, self), ($($var_names)*) -> ())
}
}
}
};
(
@arms ($name:ident, $self_:expr), ($a:ident) -> ($($body:tt)*)
) => {
$crate::enum_derive_util! {
@as_expr
match *$self_ {
$($body)*
$name::$a => $crate::std_option_Option::None
}
}
};
(
@arms ($name:ident, $self_:expr), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
) => {
$crate::NextVariant! {
@arms ($name, $self_), ($b $($rest)*)
-> (
$($body)*
$name::$a => $crate::std_option_Option::Some($name::$b),
)
}
};
}
#[macro_export]
macro_rules! PrevVariant {
(() $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(PrevVariant { @expand ($vis) $name }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis) $name:ident ()
) => {
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn prev_variant(&self) -> $crate::std_option_Option<$name> {
loop {}
}
}
}
};
(
@expand ($vis:vis) $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! {
@as_item
impl $name {
#[allow(dead_code)]
$vis fn prev_variant(&self) -> $crate::std_option_Option<$name> {
$crate::PrevVariant!(@arms ($name, self), ($crate::std_option_Option::None, $($var_names)*) -> ())
}
}
}
};
(
@arms ($name:ident, $self_:expr), ($prev:expr, $a:ident) -> ($($body:tt)*)
) => {
$crate::enum_derive_util! {
@as_expr
match *$self_ {
$($body)*
$name::$a => $prev
}
}
};
(
@arms ($name:ident, $self_:expr), ($prev:expr, $a:ident $($rest:tt)*) -> ($($body:tt)*)
) => {
$crate::PrevVariant! {
@arms ($name, $self_), ($crate::std_option_Option::Some($name::$a), $($rest)*)
-> (
$($body)*
$name::$a => $prev,
)
}
};
}
#[macro_export]
macro_rules! EnumDisplay {
(() $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(EnumDisplay { @expand $name }),
($($body)*,) -> ()
}
};
(
@expand $name:ident ()
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_fmt_Display for $name {
fn fmt(&self, _: &mut $crate::std_fmt_Formatter) -> $crate::std_fmt_Result {
loop {}
}
}
}
};
(
@expand $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_fmt_Display for $name {
fn fmt(&self, f: &mut $crate::std_fmt_Formatter) -> $crate::std_fmt_Result {
$crate::EnumDisplay!(@arms ($name, self, f), ($($var_names)*) -> ())
}
}
}
};
(
@arms ($name:ident, $self_:expr, $f:ident), ($a:ident) -> ($($body:tt)*)
) => {
$crate::enum_derive_util! {
@as_expr
match *$self_ {
$($body)*
$name::$a => write!($f, stringify!($a)),
}
}
};
(
@arms ($name:ident, $self_:expr, $f:ident), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
) => {
$crate::EnumDisplay! {
@arms ($name, $self_, $f), ($b $($rest)*)
-> (
$($body)*
$name::$a => write!($f, stringify!($a)),
)
}
};
}
#[macro_export]
macro_rules! EnumFromStr {
(() $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unitary_variants
(EnumFromStr { @expand ($vis) $name }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis) $name:ident ()
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_str_FromStr for $name {
type Err = $crate::ParseEnumError;
fn from_str(_: &str) -> $crate::std_result_Result<Self, Self::Err> {
$crate::std_result_Result::Err($crate::ParseEnumError)
}
}
}
};
(
@expand ($vis:vis) $name:ident ($($var_names:ident),*)
) => {
$crate::enum_derive_util! {
@as_item
impl $crate::std_str_FromStr for $name {
type Err = $crate::ParseEnumError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
$crate::EnumFromStr!(@arms ($name, s), ($($var_names)*) -> ())
}
}
}
};
(
@arms ($name:ident, $s:ident), ($a:ident) -> ($($body:tt)*)
) => {
$crate::enum_derive_util! {
@as_expr
match $s {
$($body)*
stringify!($a) => $crate::std_result_Result::Ok($name::$a),
_ => $crate::std_result_Result::Err($crate::ParseEnumError)
}
}
};
(
@arms ($name:ident, $s:ident), ($a:ident $b:ident $($rest:tt)*) -> ($($body:tt)*)
) => {
$crate::EnumFromStr! {
@arms ($name, $s), ($b $($rest)*)
-> (
$($body)*
stringify!($a) => $crate::std_result_Result::Ok($name::$a),
)
}
};
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParseEnumError;
impl core::fmt::Display for ParseEnumError {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
write!(fmt, "provided string did not match any enum variant")
}
}
#[cfg(feature="std")]
impl std::error::Error for ParseEnumError {
fn description(&self) -> &str {
"provided string did not match any enum variant"
}
}
#[macro_export]
macro_rules! EnumFromInner {
(() $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unary_variants
(EnumFromInner { @expand $name }),
($($body)*,) -> ()
}
};
(
@expand $name:ident ($($var_names:ident($var_tys:ty),)*)
) => {
$(
impl $crate::std_convert_From<$var_tys> for $name {
fn from(v: $var_tys) -> $name {
$name::$var_names(v)
}
}
)*
};
}
#[macro_export]
macro_rules! EnumInnerAsTrait {
($arg:tt $vis:vis enum $name:ident { $($body:tt)* }) => {
$crate::enum_derive_util! {
@collect_unary_variants
(EnumInnerAsTrait { @expand $arg, $name, }),
($($body)*,) -> ()
}
};
(
@expand ($vis:vis $fn_name:ident -> &mut $tr:ty), $($tail:tt)*
) => {
$crate::EnumInnerAsTrait! { @expand_inner ($vis), $fn_name, (mut), $tr, $($tail)* }
};
(
@expand ($vis:vis $fn_name:ident -> &$tr:ty), $($tail:tt)*
) => {
$crate::EnumInnerAsTrait! { @expand_inner ($vis), $fn_name, (), $tr, $($tail)* }
};
(
@expand_inner
($vis:vis), $fn_name:ident, (mut), $tr:ty,
$ty_name:ident,
($($var_names:ident($_var_tys:ty),)*)
) => {
$crate::enum_derive_util! {
@as_item
impl $ty_name {
$vis fn $fn_name(&mut self) -> &mut $tr {
match *self {
$(
$ty_name::$var_names(ref mut v) => v as &mut $tr,
)*
}
}
}
}
};
(
@expand_inner
($vis:vis), $fn_name:ident, (), $tr:ty,
$ty_name:ident,
($($var_names:ident($_var_tys:ty),)*)
) => {
$crate::enum_derive_util! {
@as_item
impl $ty_name {
$vis fn $fn_name(&self) -> &$tr {
match *self {
$(
$ty_name::$var_names(ref v) => v as &$tr,
)*
}
}
}
}
};
}