Macro enumeration::enumerate
source · macro_rules! enumerate { ($(#[$enum_attr:meta])* $visibility:vis $name:ident ($t:ident) $($(#[$attr:meta])* $variant:ident $(,)? $(;)?)*) => { ... }; ($(#[$enum_attr:meta])* $visibility:vis enum $name:ident ($t:ident) $($(#[$attr:meta])* $variant:ident $(,)? $(;)?)*) => { ... }; ($(#[$enum_attr:meta])* $visibility:vis enum $name:ident ($t:ident; $(#[$default_attr:meta])* $associated_value_type:ty $(= $default_value:expr)?) $($(#[$attr:meta])* $variant:ident $(= $associated_value:expr)? $(,)? $(;)?)*) => { ... }; ($(#[$enum_attr:meta])* $visibility:vis $name:ident ($t:ident; $(#[$default_attr:meta])* $associated_value_type:ty $(= $default_value:expr)?) $($(#[$attr:meta])* $variant:ident $(= $associated_value:expr)? $(,)? $(;)?)*) => { ... }; }
Expand description
This macro helps to create enum with trait Enumeration.
You have to pass in
- attributes (optional)
- a visibility qualifier (optional)
- a name
- a type this enumeration can cast to
- a type for associated constant values (optional)
- a default value for associated constant values (optional)
- at least a variant
- attributes (before variant) (optional)
- with associated constant value (only if the type is given) (optional only if default is given)
Note that commas after each variant isn’t a must (;
works too).
You can also specify enum after visibility
All patterns that start with @ is for internal macro implementation only.
Simple usage
enumerate!(pub Foo(u8)
Bar
Baz
);
produces
pub enum Foo {
Bar,
Baz,
}
with Enumeration implementation.
Syntax
You might notice that there is no comma after each variant. The macro offers multiple syntax branch that will improve readability and comply to official Rust syntax guidelines.
enumerate!(pub enum Foo(u8) // enum is optional but suggested by official Rust syntax guidelines (https://rust-lang.github.io/api-guidelines/macros.html#input-syntax-is-evocative-of-the-output-c-evocative)
Bar, // comma is optional
Baz; // semicolon works too!
);
Casting between index and enumeration
enumerate!(Foo(u8)
Bar
Baz
);
assert_eq!(Foo::variant(0)?, Foo::Bar);
assert_eq!(Foo::variant(1)?, Foo::Baz);
assert_eq!(Foo::Bar.index(), 0);
assert_eq!(Foo::Baz.index(), 1);
assert!(Foo::variant(2).is_err());
Associated constant values
enumerate!(Foo(u8; i32)
Bar = 10
Baz = 20
);
produces
enum Foo {
Bar,
Baz,
}
impl Enumeration for Foo {
fn value(&self) -> &'static i32 {
const Bar: i32 = 10;
const Baz: i32 = 20;
match self {
Foo::Bar => &Bar,
Foo::Baz => &Baz,
}
}
}
fn example() {
println!("{}", Foo::Bar.value()); // prints 10
println!("{}", Foo::Baz.value()); // prints 20
}
Default constant value
enumerate!(Foo(u8; i32 = 20)
Bar
Baz = 10
);
produces
enum Foo {
Bar,
Baz,
}
impl Enumeration for Foo {
const DEFAULT_VARIANT_ASSOCIATED_VALUE: Option<i32> = Some(20);
fn value(&self) -> &'static i32 {
const Bar: Option<i32> = None;
const Baz: Option<i32> = Some(10);
match self {
Foo::Bar => Bar.as_ref().or(Self::DEFAULT_VARIANT_ASSOCIATED_VALUE.as_ref()).unwrap(),
Foo::Baz => Baz.as_ref().or(Self::DEFAULT_VARIANT_ASSOCIATED_VALUE.as_ref()).unwrap(),
}
}
}
fn example() {
println!("{}", Foo::Bar.value()); // prints 20
println!("{}", Foo::Baz.value()); // prints 10
}
Note that default constant value is only created once, so the reference to it will always be same.
The macro will emit error if neither associated constant value nor default constant value is provided.
enumerate!(Foo(u8; i32)
Bar
Baz = 10
);
Visibility
enumerate!(pub Foo(u8)
Bar
);
enumerate!(Baz(u8)
FooBar
);
Attributes
Attributes can be attached to enumeration itself, default constant value and each of the variants. It’s most useful for documentation.
enumerate!(#[doc="An enumeration named Foo"] pub Foo(u8; #[doc="Overwrite default constant value's documentation"] i32 = 0)
#[doc="Bar"] Bar
#[doc="Baz"] Baz
);
Examples
enumerate!(pub Color(u8; &'static str)
Red = "#FF0000"
Blue = "#0000FF"
Yellow = "#FFFF00"
Cyan = "#00FFFF"
);
enumerate!(State(u8)
None
Stationary
Moving
);