1 unstable release
0.1.0 | Aug 27, 2022 |
---|
#1266 in Rust patterns
71KB
152 lines
vnum
Create enums with a constant value associated to every variant.
Features
- Get the values via the
.value()
method or via the From / Into Traits - Your attributes (
#[...]
) and documentation are automatically added to the generated enum - Documentation is generated showing the value of each variant: Image
Examples
value_enum! {
enum Fruit: &'static str {
Apple = "red",
Banana = "yellow",
Pear = "green"
}
}
// Get the value with the `.value()` method:
let apple = Fruit::Apple;
println!("Apple: {}", apple.value()); // Apple: red
// Get the value with the From / Into traits:
let pear = Fruit::Pear;
let value: &str = pear.into();
println!("Pear: {}", value); // Pear: green
Note:
The type of the values must be specified after the enum name, just like above (&'static str
in this case).
Note:
If the value type is a reference (&
) or contains references, the
'static
lifetime must be used,
otherwise the Rust compiler would not know where the value is borrowed from.
value_enum! {
#[derive(Debug)]
enum Color: u8 {
Red = 1,
Green = 2,
Yellow = 3
}
}
let red = Color::Red;
println!("{:?}: {}", red, red.value()); // Red: 1
let yellow = Color::Yellow;
let value: u8 = yellow.into();
println!("Yellow: {}", value); // Yellow: 3
Note:
If you want more traits implemented for your enum, you have to do it yourself.
In the example above, the
Debug
trait is derived.
Note:
Only constant expressions are allowed to the right of the equals sign,
which means they must be evaluable at compile time.
Look here for all kinds of constant expressions: https://doc.rust-lang.org/reference/const_eval.html#constant-expressions
Alternatives
-
Simple constants
Easy, but you can't:
- limit the possible values
- add additional items (e.g. methods, trait impl's, constants)
Example of using simple constants:
const RED: u8 = 1; const GREEN: u8 = 2; const YELLOW: u8 = 3; fn display_color(color: u8) { } display_color(RED); display_color(GREEN); // But also accepts other `u8` values: display_color(42);
You could additionally:
-
Create a type alias to improve readability:
type Color = u8; // `Color` is now an alias for `u8` fn display_color(color: Color) { } display_color(RED); // Note: Because `Color` is only an alias and not a new type, // you can still use any other `u8` value: display_color(42);
-
Put the constants in an own module to use them like
Color::RED
:mod Color { const RED: u8 = 1; // ... }
-
Enum with disciminators
- Enum
disciminators
can only be integers,
so you wouldn't be able to recreate the&str
example from above.
You can cast variants to an integer type viaas
.
Example of using an enum with disciminators:
enum Color { Red = 1, Green = 2, Yellow = 3 } fn display_color(color: Color) { // Now cast to any integer type via `as`: takes_u8(color as u8); takes_i32(color as i32); } display_color(Color::Yellow);
You could additionally:
-
Create a method to get the value:
impl Color { fn value(&self) -> u8 { self as u8 } } // ... takes_u8(color.value()) // ...
- Enum
disciminators
can only be integers,
-
Manually convert from enum variant to value
This is exactly what this library does automatically.\
Example of manually converting from enum variant to value:
enum Color { Red, Green, Yellow } impl Color { const fn value(&self) -> u8 { const RED: u8 = 1; const GREEN: u8 = 2; const YELLOW: u8 = 3; match self { Color::Red => RED, Color::Green => GREEN, Color::Yelllow => YELLOW } } } display_color(Color::Yellow); fn display_color(color: Color) { // Now cast to any integer type via `as`: takes_u8(color as u8); takes_i32(color as i32); }
Note:
Apart from generating a method like this, this libarary generates documentation and a From implementation.
Look at the beginning of the file for more information.
Planned features
- Allow creating multiple value enums in one macro invocation
- Option to ensure unique values
- Option to disable automatic documentation generation
- Make the note about the value type in the generated docs clickable
(currently doesn't work because rustdoc only creates links for types which are/contain no references) - no_std support
- Maybe:
- Get variant by value
- Optional "wildcard" variant which can hold all values of the type
- Make the names of duplicate values aliases like in pythons enum module
- Optional Debug implementation which shows the variant name and value, also like in pythons enum module
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.