macro_rules! enumerable_enum {
(
#[repr($t:ty)]
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:expr)?),+ $(,)?
}
) => { ... };
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:expr)?),+ $(,)?
}
) => { ... };
(@enum
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$($(#[$variant_meta:meta])* $variant:ident),+ $(,)?
}
) => { ... };
(@enum
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:expr)?),+ $(,)?
}
) => { ... };
}Expand description
Macro to generate helpers for fieldless unit-only enums.
Helpers for accessing variants:
COUNT: The number of variants.ALL: All variants (reference to a static array).iter():Iteratorover all variants.
Helpers for converting to and from the discriminant (requires the enum to have an explicit
#[repr(...)] attribute before all other attributes):
checked_from_discriminant()&from_discriminant(): Safe and panicking conversions from the discriminant.Fromimplementation from the enum to the discriminant.TryFromimplementation from the discriminant to the enum.
Helpers for using variants as array indices (requires all variants to use implicit discriminants):
See also parser::parsable_enum!, which combined this macro
with building a parser.
§Examples
Variant helpers:
utils::enumerable_enum! {
enum Direction {
North,
East,
South,
West,
}
}
assert_eq!(Direction::COUNT, 4);
assert!(matches!(Direction::ALL, &[
Direction::North,
Direction::East,
Direction::South,
Direction::West,
]));
assert!(matches!(Direction::iter().collect::<Vec<_>>().as_slice(), &[
Direction::North,
Direction::East,
Direction::South,
Direction::West,
]));Discriminant helpers:
utils::enumerable_enum! {
#[repr(u8)]
#[derive(Copy, Clone, Debug, Default, PartialEq)]
enum Operation {
Add,
Sub,
Mul,
Div,
#[default]
Noop = 255,
}
}
assert_eq!(Operation::COUNT, 5);
assert_eq!(Operation::ALL, &[
Operation::Add,
Operation::Sub,
Operation::Mul,
Operation::Div,
Operation::Noop
]);
assert_eq!(Operation::iter().collect::<Vec<_>>(), Operation::ALL);
assert_eq!(Operation::from_discriminant(0), Operation::Add);
assert_eq!(Operation::checked_from_discriminant(255), Some(Operation::Noop));
assert_eq!(Operation::checked_from_discriminant(100), None);
assert_eq!(u8::from(Operation::Add), 0u8);
assert_eq!(Operation::try_from(2u8), Ok(Operation::Mul));
assert_eq!(Operation::try_from(4u8), Err(()));from_discriminant panics on invalid values:
ⓘ
utils::enumerable_enum! {
#[repr(u8)]
enum Operation {
Add,
Sub,
Mul,
Div,
}
}
Operation::from_discriminant(64);Index helpers:
utils::enumerable_enum! {
enum Register {
A,
B,
C,
D,
}
}
let mut registers = [0, 1, 2, 3];
assert_eq!(registers[Register::A], 0);
assert_eq!(registers[Register::B], 1);
assert_eq!(registers[Register::C], 2);
assert_eq!(registers[Register::D], 3);
registers[Register::C] = 123;
assert_eq!(registers[Register::C], 123);