Skip to content

01. Structs, Enums & Pattern Matching

Structs and Enums are the building blocks for custom types in Rust.

Structs

Structs allow you to name and package multiple related values into a single entity.

Classic Structs

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

let user1 = User {
    email: String::from("someone@example.com"),
    username: String::from("someuser123"),
    active: true,
    sign_in_count: 1,
};

Tuple Structs

Tuple structs have names but their fields don’t. Use them for small, simple groupings.

struct Color(i32, i32, i32);
let black = Color(0, 0, 0);

Methods in Structs

Methods are defined within an impl block. They take &self (immutable), &mut self (mutable), or self (consume ownership) as their first parameter.

impl User {
    fn display_info(&self) {
        println!("Username: {}, Email: {}", self.username, self.email);
    }
}

Enums

Enums (enumerations) allow you to define a type by enumerating its possible variants.

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

Rust enums are Algebraic Data Types (ADTs), meaning each variant can store different types of data.

Pattern Matching with match

Pattern matching is a powerful control flow operator that compares a value against a series of patterns.

let msg = Message::Write(String::from("hello"));

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

if let Syntax

If you only care about one variant, if let is a concise alternative to match.

if let Message::Write(text) = msg {
    println!("Text: {}", text);
}

In the next section, we explore the Standard Library’s powerful collection types.