Enums
Enum Syntax
Enums are custom data types that define a set of possible 'variants' or states that a value can be. A value of that enum type can only be one of those variants at any given time. Each variant can optionally hold associated data (fields) of different types like a struct
or like a tuple
:
/// An enum to represent different types of messages. #[derive(Debug)] enum Message { Quit, // Unit-like variant (no fields). Move { x: i32, y: i32 }, // Struct-like variant (named fields). Write(String), // Tuple-like variant (numbered fields). ChangeColor(i32, i32, i32), // Another tuple-like variant. } /// Define methods on enums. impl Message { fn call(&self) { // The `match` keyword allows us to compare a value against a series of // patterns. Each pattern can have associated code that will be // run if the value matches the pattern. match self { Message::Quit => println!("The Quit variant has no data to show."), Message::Move { x, y } => println!( "Move in the x direction {x} and in the y direction {y}" ), Message::Write(text) => println!("Message: {text}"), Message::ChangeColor(r, g, b) => { println!("Change the color to red {r}, green {g}, and blue {b}") } } // Enums make your code safer, because the compiler knows all the // possible variants a value can have, and makes sure the // `match` expression handles all possibilities. } } fn main() { // `msg` is assigned one of the variants. // Note the :: between the name of the type and the name of the variant. let msg = Message::Quit; println!("{msg:?}"); // Or let msg = Message::Move { x: 10, y: 15 }; println!("{msg:?}"); // Or let msg = Message::ChangeColor(127, 0, 0); println!("{msg:?}"); let msg = Message::Write(String::from("hello")); msg.call(); }
If we make an enum public, all of its variants are then public. We only need pub
⮳ before the enum
⮳ keyword.
Common enums
- Option.
- Result.
Convert between Strings and Enum Variants with strum
strum
⮳ provides helpful macros for working with enums and strings. It also can convert from an integer to an enum, add custom properties to enum variants, etc.
//! `strum` provides derive macros that automatically implement various traits //! for your enums, making it easy to convert them to and from strings, iterate //! over their variants, and more. //! //! Add to your `Cargo.toml`: //! ```toml //! [dependencies] //! strum = { version = "0.27", features = ["derive"] } //! ``` use strum::Display; use strum::EnumIter; use strum::EnumString; use strum::IntoEnumIterator; // Import the trait to use .iter(). // We derive a few `strum` traits in addition to standard `Debug` and // `PartialEq`: // - `Display` to easily print the enum variant as a string, // - `EnumString` to parse a string into an enum variant, // - `EnumIter` to iterate over all possible variants of the enum. #[derive(Debug, Display, EnumString, EnumIter, PartialEq)] enum Direction { #[strum(serialize = "N")] // Customize the `Display` representation. North, #[strum(serialize = "E")] East, #[strum(serialize = "S")] South, #[strum(serialize = "W")] West, } fn main() { println!("--- Displaying Enum Variants ---"); let dir = Direction::North; // Using the `Display` trait. println!("Current direction: {}", dir); // Prints "Current direction: North". println!("\n--- Parsing Strings into Enums ---"); let input_string_south = "South"; let input_string_invalid = "Up"; // Using the EnumString trait: match input_string_south.parse::<Direction>() { Ok(direction) => println!( "Parsed '{}' successfully: {:?}.", input_string_south, direction ), Err(e) => println!("Failed to parse '{}': {}.", input_string_south, e), } match input_string_invalid.parse::<Direction>() { Ok(direction) => println!( "Parsed '{}' successfully: {:?}.", input_string_invalid, direction ), Err(e) => { println!("Failed to parse '{}': {}.", input_string_invalid, e) } } println!("\n--- Iterating Over Enum Variants ---"); // Using the `EnumIter` trait: println!("All possible directions:"); for direction in Direction::iter() { println!("- {:?}", direction); } // This will print: // - North // - East // - South // - West }
Related Topics
- Match.
- Rust Patterns.
- Functional Programming.
- Data Types.
- Structs.