Rust Enums

Defining types with multiple possible variants

🎯 What are Enums?

Enums define types with multiple possible variants, each potentially holding different data. They're perfect for representing states, options, and choices in your programs safely.


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

Enum Features

📝

Simple Variants

Basic enum variants

enum Status {
    Active,
    Inactive,
}
📦

Data Variants

Variants that hold data

enum Message {
    Text(String),
    Number(i32),
}
🔧

Methods

Functions on enums

impl Status {
    fn is_active(&self) {}
}
🎛️

Option & Result

Built-in useful enums

Option
Result

🔹 Basic Enums

Simple enums with named variants:

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

fn main() {
    let light = TrafficLight::Red;
    
    match light {
        TrafficLight::Red => println!("Stop!"),
        TrafficLight::Yellow => println!("Caution!"),
        TrafficLight::Green => println!("Go!"),
    }
    
    // Using if let
    if let TrafficLight::Red = light {
        println!("The light is red");
    }
}

Output:

Stop!
The light is red

🔹 Enums with Data

Enum variants can hold different types of data:

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

impl Message {
    fn process(&self) {
        match self {
            Message::Quit => println!("Quitting..."),
            Message::Move { x, y } => println!("Moving to ({}, {})", x, y),
            Message::Write(text) => println!("Writing: {}", text),
            Message::ChangeColor(r, g, b) => println!("Changing color to RGB({}, {}, {})", r, g, b),
        }
    }
}

fn main() {
    let messages = vec![
        Message::Write(String::from("Hello")),
        Message::Move { x: 10, y: 20 },
        Message::ChangeColor(255, 0, 0),
        Message::Quit,
    ];
    
    for message in messages {
        message.process();
    }
}

Output:

Writing: Hello
Moving to (10, 20)
Changing color to RGB(255, 0, 0)
Quitting...

🔹 Option Enum

Rust's built-in Option enum for handling null values safely:

fn find_word(text: &str, word: &str) -> Option {
    text.find(word)
}

fn main() {
    let sentence = "Hello, world!";
    
    match find_word(sentence, "world") {
        Some(index) => println!("Found 'world' at index {}", index),
        None => println!("'world' not found"),
    }
    
    match find_word(sentence, "rust") {
        Some(index) => println!("Found 'rust' at index {}", index),
        None => println!("'rust' not found"),
    }
    
    // Using unwrap_or for default values
    let index = find_word(sentence, "hello").unwrap_or(0);
    println!("Index with default: {}", index);
}

Output:

Found 'world' at index 7
'rust' not found
Index with default: 0

🔹 Result Enum

Handle operations that might fail with Result:

fn divide(a: f64, b: f64) -> Result {
    if b == 0.0 {
        Err(String::from("Cannot divide by zero"))
    } else {
        Ok(a / b)
    }
}

fn main() {
    let results = vec![
        divide(10.0, 2.0),
        divide(10.0, 0.0),
        divide(15.0, 3.0),
    ];
    
    for result in results {
        match result {
            Ok(value) => println!("Result: {}", value),
            Err(error) => println!("Error: {}", error),
        }
    }
    
    // Using unwrap_or for error handling
    let safe_result = divide(20.0, 0.0).unwrap_or(-1.0);
    println!("Safe result: {}", safe_result);
}

Output:

Result: 5
Error: Cannot divide by zero
Result: 5
Safe result: -1

🧠 Test Your Knowledge

Which Rust enum is used to handle values that might not exist?