Rust: structs

·

3 min read

Play this article

In Rust, an entire instance of a struct must be mutable; the language doesn't permit marking only specific fields as mutable. By constructing a new instance of the struct as the final expression in the function body, you can implicitly return that new instance.

A struct in Rust is a custom data type that enables you to group and name multiple related values, forming a coherent package.

There are three types of structs:

  1. Structs with Named Fields: These are typical object declarations with key-value pairs. If you wish to change a property value of a struct, its instance must be mutable. The "field init shorthand" is a convenient feature allowing you to set a field value with a single word when the variable names match:

     // Not recommended
     User {
         name: name,
     }
    
     // Recommended
     User {
         name,
     }
    

    The "update syntax" lets you borrow values from another struct instance when creating a new one. This can simplify initialization of new struct instances by borrowing from existing ones. For fields that don't implement the Copy trait, their values will be moved, rendering the old instance unusable:

     let new_user = User {
         email: "new_user@ema.il",
         ..old_user
     }
    
  2. Tuple Structs: These are structs without named fields. You access the fields using their index, starting from 0. Despite having the same field types, each tuple struct is treated as a unique type:

     struct RgbColor(i32, i32, i32);
     struct Location(u32, u32);
    
  3. Unit-like Structs: These are structs with no fields and can be particularly useful for traits or type definitions:

     struct PoundsOfForce(f64);
     struct AlwaysEqual;
    
     fn handle_unit_like() {
         let subject = AlwaysEqual;
     }
    

Struct Data Ownership

Structs can store both owned types (like String) and reference types (&str). When storing reference types, you must define their lifetimes, ensuring the data remains valid as long as the struct exits.

Methods and Associated Functions

Methods are introduced within an impl block, which can be separate from the struct declaration. A method can either take ownership of self, borrow self immutably, or borrow self mutably. Methods must include a self parameter, which refers to the instance of the struct.

It's noteworthy that method names can match struct field names. Often, methods with the same name as a field (known as getters) are used to grant read-only access to that field, especially when the field is private.

struct Person {
    name: String,
}

impl Person {
    fn name(&self) -> &str {
        &self.name
    }
}

Rust handles method calls with automatic referencing and dereferencing. This means that when calling a method, Rust will automatically add in &, &mut, or * to ensure the method signature matches the called object.

All Struct Concepts in a Code Example

rustCopy code
// Struct with named fields
struct Person {
    name: String,
    surname: String,
    location: Position,
}

impl Person {
    // In the context of this struct, "self" refers to the instance and "Self" refers to the type of the struct.
    fn describe(&self) {
        println!("Full Name: {} {}", self.name, self.surname);
        println!("Your current location is: x: {} / y: {}", self.location.0, self.location.1);
    }

    // Associated functions are accessed using '::' notation.
    fn new(name: String) -> Self {
        Self {
            name,
            surname: "What".to_string(),
            location: Position(1, 2, 3),
        }
    }
}

fn spawn(Person { location: Position(x, y, ..), name, .. }: Person) {
    println!("{} spawned at {} {}", name, x, y);
}

fn main() {
    let person = Person::new("art".to_string());
    let female = Person::new("maria".to_string());

    person.describe();

    // Destructure a struct
    let Person { name, location, .. } = person;
    spawn(female);
    println!("person {} is at {} {}", name, location.0, location.1);
    todo!("I need to refactor this");
}

Reference

Best Video Material

[YouTube] 300 seconds of Rust - 10. Enums and Match

[YouTube] 300 seconds of Rust - 9. Structs

Best Text Material

The Rust Programming Language: Structs

The Rust Programming Language: Enums