Enums and Pattern Matching

Nested Patterns

Rust patterns are composable: any place where a variable binding can appear inside a tuple, struct, enum variant, array, slice, or reference pattern can instead contain another pattern, allowing deeply nested data structures to be matched and destructured in a single step.

Composing Enums, Structs, Tuples, and Slices

Nested Pattern Hierarchy:

  Event::HttpRequest {
      method: Method::Post,                  <-- Nested unit enum variant
      headers: [first_hdr, ..],              <-- Nested slice pattern
      body: Some(Payload::Json { bytes }),   <-- Nested Option + struct-variant pattern
  }
#[derive(Debug)]
enum Color {
    Rgb(u8, u8, u8),
    Hsv { h: u16, s: u8, v: u8 },
}

#[derive(Debug)]
enum Shape {
    Circle { radius: u32, fill: Color },
    Rectangle { width: u32, height: u32, fill: Color },
}

fn describe_shape(shape: &Shape) {
    match shape {
        // Match a Circle filled with pure black RGB(0, 0, 0):
        Shape::Circle {
            radius,
            fill: Color::Rgb(0, 0, 0),
        } => {
            println!("Black circle of radius {radius}");
        }

        // Match any Circle filled with RGB and bind `r`, `g`, `b`:
        Shape::Circle {
            radius,
            fill: Color::Rgb(r, g, b),
        } => {
            println!("Circle (r={radius}) with RGB({r}, {g}, {b})");
        }

        // Match a square (`width == height` via match guard) with HSV fill:
        Shape::Rectangle {
            width,
            height,
            fill: Color::Hsv { h, s, v },
        } if width == height => {
            println!("Square ({width}x{height}) with HSV({h}°, {s}%, {v}%)");
        }

        // Fallback for any other shape combination:
        other => println!("Other shape: {other:?}"),
    }
}

fn main() {
    let s1 = Shape::Circle {
        radius: 10,
        fill: Color::Rgb(0, 0, 0),
    };
    let s2 = Shape::Circle {
        radius: 25,
        fill: Color::Rgb(255, 128, 0),
    };
    let s3 = Shape::Rectangle {
        width: 50,
        height: 50,
        fill: Color::Hsv { h: 180, s: 80, v: 90 },
    };

    describe_shape(&s1);
    describe_shape(&s2);
    describe_shape(&s3);
}
Black circle of radius 10
Circle (r=25) with RGB(255, 128, 0)
Square (50x50) with HSV(180°, 80%, 90%)

Matching Nested Result<Option<T>, E> Values

Functions that read optional records from fallible I/O or databases often return Result<Option<T>, E>. Matching the nested structure directly handles every combination in one flat match block:

fn lookup_port(env_Result: Result<Option<u16>, &'static str>) -> u16 {
    match env_Result {
        Ok(Some(0)) => {
            println!("Port 0 is reserved; falling back to 8080");
            8080
        }
        Ok(Some(port)) => port,
        Ok(None) => 8080, // Not configured; use default
        Err(reason) => {
            println!("Config error ({reason}); falling back to 8080");
            8080
        }
    }
}

fn main() {
    println!("Result 1: {}", lookup_port(Ok(Some(3000))));
    println!("Result 2: {}", lookup_port(Ok(Some(0))));
    println!("Result 3: {}", lookup_port(Ok(None)));
    println!("Result 4: {}", lookup_port(Err("permission denied")));
}
Result 1: 3000
Port 0 is reserved; falling back to 8080
Result 2: 8080
Result 3: 8080
Config error (permission denied); falling back to 8080
Result 4: 8080