Core Concepts

Structs and Enums

Define custom data types with structs and enums — Rust's powerful algebraic type system.

Structs

Structs group related data. Rust has three kinds:

  • Named field structs (most common)
  • Tuple structs (struct Point(f32, f32);)
  • Unit structs (no fields, for type-level logic)

Methods on Structs

Use impl blocks to add methods to structs.

Enums

Rust enums can hold data — each variant can have different types and amounts of data. This makes them incredibly powerful.

Option and Result

Two fundamental Rust enums:

  • Option<T>: Either Some(value) or None
  • Result<T, E>: Either Ok(value) or Err(error)

Example

rust
#[derive(Debug, Clone)]
struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    // Associated function (constructor)
    fn new(width: f64, height: f64) -> Self {
        Rectangle { width, height }
    }

    fn square(size: f64) -> Self {
        Rectangle { width: size, height: size }
    }

    // Methods take &self, &mut self, or self
    fn area(&self) -> f64 {
        self.width * self.height
    }

    fn is_square(&self) -> bool {
        self.width == self.height
    }
}

// Enum with data
#[derive(Debug)]
enum Shape {
    Circle(f64),              // radius
    Rectangle(f64, f64),      // width, height
    Triangle(f64, f64, f64),  // three sides
}

impl Shape {
    fn area(&self) -> f64 {
        match self {
            Shape::Circle(r) => std::f64::consts::PI * r * r,
            Shape::Rectangle(w, h) => w * h,
            Shape::Triangle(a, b, c) => {
                let s = (a + b + c) / 2.0;
                (s * (s - a) * (s - b) * (s - c)).sqrt()
            }
        }
    }
}

fn main() {
    let rect = Rectangle::new(5.0, 3.0);
    println!("Area: {}, Is square: {}", rect.area(), rect.is_square());
    println!("{:?}", rect);

    let shapes = vec![
        Shape::Circle(4.0),
        Shape::Rectangle(3.0, 5.0),
        Shape::Triangle(3.0, 4.0, 5.0),
    ];

    for shape in &shapes {
        println!("{:?} area: {:.2}", shape, shape.area());
    }

    // Option<T>
    let some_number: Option<i32> = Some(42);
    let no_number: Option<i32> = None;

    if let Some(n) = some_number {
        println!("Got: {}", n);
    }

    let value = no_number.unwrap_or(0);  // 0 if None
    println!("Value: {}", value);
}
Try it yourself — RUST