Skip to content

Commit

Permalink
Support omitted discriminants
Browse files Browse the repository at this point in the history
Closes: #1

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Loading branch information
andersk committed Apr 8, 2015
1 parent 173a5a8 commit e12402c
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 24 deletions.
100 changes: 76 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@
//! enum FooBar {
//! Foo = 17,
//! Bar = 42,
//! Baz,
//! }
//! }
//!
//! fn main() {
//! assert_eq!(FooBar::from_i32(17), Some(FooBar::Foo));
//! assert_eq!(FooBar::from_i32(42), Some(FooBar::Bar));
//! assert_eq!(FooBar::from_i32(43), Some(FooBar::Baz));
//! assert_eq!(FooBar::from_i32(91), None);
//! }
//! ```
Expand All @@ -63,7 +65,7 @@ pub use num::FromPrimitive;
/// Helper macro for internal use by `enum_from_primitive!`.
#[macro_export]
macro_rules! enum_from_primitive_impl_ty {
($meth:ident, $ty:ty, $name:ident, $( $variant:ident ),*) => {
($meth:ident, $ty:ty, $name:ident, $( $variant:ident )*) => {
#[allow(non_upper_case_globals, unused)]
fn $meth(n: $ty) -> $crate::Option<Self> {
$( if n == $name::$variant as $ty {
Expand All @@ -72,19 +74,19 @@ macro_rules! enum_from_primitive_impl_ty {
$crate::Option::None
}
}
}
};
}

/// Helper macro for internal use by `enum_from_primitive!`.
#[macro_export]
#[macro_use(enum_from_primitive_impl_ty)]
macro_rules! enum_from_primitive_impl {
($name:ident, $( $variant:ident ),*) => {
($name:ident, $( $variant:ident )*) => {
impl $crate::FromPrimitive for $name {
enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant ),* }
enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant ),* }
enum_from_primitive_impl_ty! { from_i64, i64, $name, $( $variant )* }
enum_from_primitive_impl_ty! { from_u64, u64, $name, $( $variant )* }
}
}
};
}

/// Wrap this macro around an `enum` declaration to get an
Expand All @@ -95,54 +97,104 @@ macro_rules! enum_from_primitive {
(
$( #[$enum_attr:meta] )*
enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
}
) => {
$( #[$enum_attr] )*
enum $name {
$( $( #[$variant_attr] )* $variant = $discriminator ),*
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
}
enum_from_primitive_impl! { $name, $($variant),* }
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
};

(
$( #[$enum_attr:meta] )*
enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*,
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
}
) => {
enum_from_primitive! {
$( #[$enum_attr] )*
enum $name {
$( $( #[$variant_attr] )* $variant = $discriminator ),*
}
$( #[$enum_attr] )*
enum $name {
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
}
enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
};

(
$( #[$enum_attr:meta] )*
enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
}
) => {
$( #[$enum_attr] )*
enum $name {
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
}
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
};

(
$( #[$enum_attr:meta] )*
enum $name:ident {
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
}
) => {
$( #[$enum_attr] )*
enum $name {
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
}
enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
};

(
$( #[$enum_attr:meta] )*
pub enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*
}
) => {
$( #[$enum_attr] )*
pub enum $name {
$( $( #[$variant_attr] )* $variant = $discriminator ),*
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*
}
enum_from_primitive_impl! { $name, $( $variant ),* }
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
};

(
$( #[$enum_attr:meta] )*
pub enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),*,
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),*
}
) => {
enum_from_primitive! {
$( #[$enum_attr] )*
pub enum $name {
$( $( #[$variant_attr] )* $variant = $discriminator ),*
}
$( #[$enum_attr] )*
pub enum $name {
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),*
}
enum_from_primitive_impl! { $name, $( $( $variant )+ )* }
};

(
$( #[$enum_attr:meta] )*
pub enum $name:ident {
$( $( #[$variant_attr:meta] )* $variant:ident ),+ $( = $discriminator:expr, $( $( #[$variant_two_attr:meta] )* $variant_two:ident ),+ )*,
}
) => {
$( #[$enum_attr] )*
pub enum $name {
$( $( #[$variant_attr] )* $variant ),+ $( = $discriminator, $( $( #[$variant_two_attr] )* $variant_two ),+ )*,
}
enum_from_primitive_impl! { $name, $( $variant )+ $( $( $variant_two )+ )* }
};

(
$( #[$enum_attr:meta] )*
pub enum $name:ident {
$( $( $( #[$variant_attr:meta] )* $variant:ident ),+ = $discriminator:expr ),+,
}
) => {
$( #[$enum_attr] )*
pub enum $name {
$( $( $( #[$variant_attr] )* $variant ),+ = $discriminator ),+,
}
enum_from_primitive_impl! { $name, $( $( $variant )+ )+ }
};
}
63 changes: 63 additions & 0 deletions tests/omitted-discriminants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#[macro_use] extern crate enum_primitive;

enum_from_primitive! { enum E { } }
enum_from_primitive! { enum E0 { V0 } }
enum_from_primitive! { enum E0C { V0, } }
enum_from_primitive! { enum E1 { V0 = 0 } }
enum_from_primitive! { enum E1C { V0 = 0, } }
enum_from_primitive! { enum E00 { V0, V1 } }
enum_from_primitive! { enum E00C { V0, V1, } }
enum_from_primitive! { enum E01 { V0, V1 = 1 } }
enum_from_primitive! { enum E01C { V0, V1 = 1, } }
enum_from_primitive! { enum E10 { V0 = 0, V1 } }
enum_from_primitive! { enum E10C { V0 = 0, V1, } }
enum_from_primitive! { enum E11 { V0 = 0, V1 = 1 } }
enum_from_primitive! { enum E11C { V0 = 0, V1 = 1, } }
enum_from_primitive! { enum E000 { V0, V1, V2 } }
enum_from_primitive! { enum E000C { V0, V1, V2, } }
enum_from_primitive! { enum E001 { V0, V1, V2 = 2 } }
enum_from_primitive! { enum E001C { V0, V1, V2 = 2, } }
enum_from_primitive! { enum E010 { V0, V1 = 1, V2 } }
enum_from_primitive! { enum E010C { V0, V1 = 1, V2, } }
enum_from_primitive! { enum E011 { V0, V1 = 1, V2 = 2 } }
enum_from_primitive! { enum E011C { V0, V1 = 1, V2 = 2, } }
enum_from_primitive! { enum E100 { V0 = 0, V1, V2 } }
enum_from_primitive! { enum E100C { V0 = 0, V1, V2, } }
enum_from_primitive! { enum E101 { V0 = 0, V1, V2 = 2 } }
enum_from_primitive! { enum E101C { V0 = 0, V1, V2 = 2, } }
enum_from_primitive! { enum E110 { V0 = 0, V1 = 1, V2 } }
enum_from_primitive! { enum E110C { V0 = 0, V1 = 1, V2, } }
enum_from_primitive! { enum E111 { V0 = 0, V1 = 1, V2 = 2 } }
enum_from_primitive! { enum E111C { V0 = 0, V1 = 1, V2 = 2, } }
enum_from_primitive! { enum E0000 { V0, V1, V2, V3 } }
enum_from_primitive! { enum E0000C { V0, V1, V2, V3, } }
enum_from_primitive! { enum E0001 { V0, V1, V2, V3 = 3 } }
enum_from_primitive! { enum E0001C { V0, V1, V2, V3 = 3, } }
enum_from_primitive! { enum E0010 { V0, V1, V2 = 2, V3 } }
enum_from_primitive! { enum E0010C { V0, V1, V2 = 2, V3, } }
enum_from_primitive! { enum E0011 { V0, V1, V2 = 2, V3 = 3 } }
enum_from_primitive! { enum E0011C { V0, V1, V2 = 2, V3 = 3, } }
enum_from_primitive! { enum E0100 { V0, V1 = 1, V2, V3 } }
enum_from_primitive! { enum E0100C { V0, V1 = 1, V2, V3, } }
enum_from_primitive! { enum E0101 { V0, V1 = 1, V2, V3 = 3 } }
enum_from_primitive! { enum E0101C { V0, V1 = 1, V2, V3 = 3, } }
enum_from_primitive! { enum E0110 { V0, V1 = 1, V2 = 2, V3 } }
enum_from_primitive! { enum E0110C { V0, V1 = 1, V2 = 2, V3, } }
enum_from_primitive! { enum E0111 { V0, V1 = 1, V2 = 2, V3 = 3 } }
enum_from_primitive! { enum E0111C { V0, V1 = 1, V2 = 2, V3 = 3, } }
enum_from_primitive! { enum E1000 { V0 = 0, V1, V2, V3 } }
enum_from_primitive! { enum E1000C { V0 = 0, V1, V2, V3, } }
enum_from_primitive! { enum E1001 { V0 = 0, V1, V2, V3 = 3 } }
enum_from_primitive! { enum E1001C { V0 = 0, V1, V2, V3 = 3, } }
enum_from_primitive! { enum E1010 { V0 = 0, V1, V2 = 2, V3 } }
enum_from_primitive! { enum E1010C { V0 = 0, V1, V2 = 2, V3, } }
enum_from_primitive! { enum E1011 { V0 = 0, V1, V2 = 2, V3 = 3 } }
enum_from_primitive! { enum E1011C { V0 = 0, V1, V2 = 2, V3 = 3, } }
enum_from_primitive! { enum E1100 { V0 = 0, V1 = 1, V2, V3 } }
enum_from_primitive! { enum E1100C { V0 = 0, V1 = 1, V2, V3, } }
enum_from_primitive! { enum E1101 { V0 = 0, V1 = 1, V2, V3 = 3 } }
enum_from_primitive! { enum E1101C { V0 = 0, V1 = 1, V2, V3 = 3, } }
enum_from_primitive! { enum E1110 { V0 = 0, V1 = 1, V2 = 2, V3 } }
enum_from_primitive! { enum E1110C { V0 = 0, V1 = 1, V2 = 2, V3, } }
enum_from_primitive! { enum E1111 { V0 = 0, V1 = 1, V2 = 2, V3 = 3 } }
enum_from_primitive! { enum E1111C { V0 = 0, V1 = 1, V2 = 2, V3 = 3, } }

0 comments on commit e12402c

Please sign in to comment.