Enums: One of Several Shapes
A book in the library is on the shelf, or out on loan, or lost. Never two at once. A struct full of true/false flags can describe impossible mixtures; an enum cannot. Enums are also how Rust represents "a value or nothing" and "success or failure", which is why they belong in this section on errors.
The rule
An enum is exactly one variant at a time, and each variant carries its own data.
enum Status {
OnShelf,
OnLoan { card: u32, due_day: u32 },
Lost,
}
let s = Status::OnLoan { card: 1042, due_day: 21 };- Variants are named with
Type::Variant. - A variant can hold nothing (
OnShelf), named fields (OnLoan { ... }), or unnamed ones likeDamaged(String). - The data belongs to its variant: a book on the shelf simply has no card number.
Handle an enum with match, which must cover every variant and can pull out the data:
fn describe(s: &Status) -> String {
match s {
Status::OnShelf => String::from("available"),
Status::OnLoan { card, due_day } => format!("with card {card} until day {due_day}"),
Status::Lost => String::from("lost"),
}
}Enums get impl blocks just like structs, so describe could be a method, s.describe().
When you later add a variant, say Repair, every match without a catch-all stops compiling until you handle it. That is a feature: the compiler lists every place to update.
The shortcut
Ask of any piece of data: "Is this and or or?" Title and pages and status → struct. On shelf or on loan or lost → enum. Most real types combine both.
The "and" part
Every book has a title and pages.
struct Book { title: String, pages: u32, status: Status }
The trap is modelling states as several bool fields. Two flags give four combinations, and some of them make no sense.
Drills
Answer fast — trust the rule.
How many variants can one Status value be at the same moment?
How do you create a Status value for a lost book?
A match on Status has arms for OnShelf and OnLoan only. What happens?
Why put card inside OnLoan rather than in Book?
Remember
- An enum value is exactly one variant, and each variant carries only its own data.
- "And" → struct, "or" → enum.
matchmust cover every variant, so adding one shows you every place to update.
