Rust Enums

🦀 Rust Enums

Enums (Enumerations) in Rust let you define a type that can be one of several variants.

They are extremely powerful and are a core reason why Rust code is safe, expressive, and clean.


 1. What Is an Enum?

An enum defines a type with a fixed set of possible values.

enum Direction {
North,
South,
East,
West,
}

Here, a value of Direction can be only one of these four.


 2. Creating and Using Enum Values

fn main() {
let move_dir = Direction::North;
}

Enums are often used with match.


 3. Enums with match (Very Important)

fn main() {
let dir = Direction::East;
match dir {
Direction::North => println!(“Going North”),
Direction::South => println!(“Going South”),
Direction::East => println!(“Going East”),
Direction::West => println!(“Going West”),
}
}

match must be exhaustive
✔ Compiler ensures all cases are handled


 4. Enums with Data (Power Feature 🔥)

Each enum variant can store data.

enum Message {
Quit,
Write(String),
Move { x: i32, y: i32 },
ChangeColor(i32, i32, i32),
}

Usage:

let msg1 = Message::Write(String::from("Hello"));
let msg2 = Message::Move { x: 10, y: 20 };

 5. Matching Enums with Data

fn process(msg: Message) {
match msg {
Message::Quit => println!("Quit"),
Message::Write(text) => println!("Text: {}", text),
Message::Move { x, y } => println!("Move to {}, {}", x, y),
Message::ChangeColor(r, g, b) => println!("Color {},{},{}", r, g, b),
}
}

✔ Destructuring happens naturally
✔ Very readable code


 6. Option<T> – No null in Rust

Rust does not have null.
Instead, it uses Option<T>.

enum Option<T> {
Some(T),
None,
}

Example:

fn main() {
let number: Option<i32> = Some(10);
match number {
Some(n) => println!(“Value: {}”, n),
None => println!(“No value”),
}
}

✔ Prevents null pointer errors
✔ Compiler forces you to handle missing values


 7. Result<T, E> – Error Handling

Another important enum.

enum Result<T, E> {
Ok(T),
Err(E),
}

Example:

fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err(String::from("Division by zero"))
} else {
Ok(a / b)
}
}

Usage:

match divide(10, 2) {
Ok(val) => println!("Result: {}", val),
Err(err) => println!("Error: {}", err),
}

 8. Enum Methods (impl)

Enums can have methods too.

enum Status {
Active,
Inactive,
}
impl Status {
fn is_active(&self) -> bool {
matches!(self, Status::Active)
}
}

 9. if let – Shorter Matching

When you care about only one case.

let value = Some(5);

if let Some(x) = value {
println!(“{}”, x);
}

✔ Cleaner than match for simple cases


 10. Enums vs Structs

Feature Enum Struct
Multiple variants
Different shapes
Use with match
Fixed fields

👉 Use enum when a value can be one of many forms.


❌ Common Mistakes

  • Forgetting to handle all enum cases

  • Overusing unwrap()

  • Using struct when enum fits better

  • Not leveraging enums with data


🧠 Key Takeaways

  • Enums define multiple possible states

  • Variants can store different data

  • match + enum = super power

  • Option and Result are core enums

  • Compiler enforces safety

You may also like...