# vnum Create enums with a constant value associated to every variant. ## Features - Get the values via the `.value()` method or via the [From](https://doc.rust-lang.org/stable/std/convert/trait.From.html "docs for std::convert::From") / [Into](https://doc.rust-lang.org/stable/std/convert/trait.Into.html "docs for std::convert::Into") Traits - Your attributes (`#[...]`) and documentation are automatically added to the generated enum - Documentation is generated showing the value of each variant: [Image](./assets/generated_docs_example_dark.png) ## Examples ```rust 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`](https://doc.rust-lang.org/stable/rust-by-example/scope/lifetime/static_lifetime.html) lifetime must be used,\ otherwise the Rust compiler would not know where the value is borrowed from.
```rust 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](https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html "docs for std::fmt::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: ## Alternatives - ### **Simple [constants](https://doc.rust-lang.org/reference/items/constant-items.html)** Easy, but you can't: - limit the possible values - add additional items (e.g. methods, trait impl's, constants) Example of using simple constants: ```rust 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](https://doc.rust-lang.org/reference/items/type-aliases.html) to improve readability: ```rust 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` : ```rust mod Color { const RED: u8 = 1; // ... } ```
- ### **Enum with [disciminators](https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations)** - Enum [disciminators](https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations) 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 via `as`. Example of using an enum with disciminators: ```rust 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: ```rust impl Color { fn value(&self) -> u8 { self as u8 } } // ... takes_u8(color.value()) // ... ```
- ### **Manually convert from enum variant to value** This is exactly what this library does automatically.\ Example of manually converting from enum variant to value: ```rust 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](https://doc.rust-lang.org/stable/std/convert/trait.From.html "docs for std::convert::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](https://doc.rust-lang.org/stable/reference/names/preludes.html#the-no_std-attribute) 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](https://docs.python.org/3/library/enum.html) - Optional [Debug](https://doc.rust-lang.org/stable/std/fmt/trait.Debug.html "docs for std::fmt::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](LICENSE-APACHE) or ) - MIT license ([LICENSE-MIT](LICENSE-MIT) or ) 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.