Structs

Rust by example - Structs

/// We first define the struct's fields (which can be of any type).
/// The `User` struct has four fields: `active`, `username`, `email`, and
/// `sign_in_count`.
#[derive(Debug)]
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}
// The `derive(Debug)` attribute is not required - it just enables `println!`
// below.

/// The `main` function creates an instance of the `User` struct.
/// It then prints the struct to the console.
fn main() {
    // Note that there is no `new` or similar.
    let user1 = User {
        active: true,
        username: String::from("someusername123"),
        email: String::from("someone@example.com"),
        sign_in_count: 1,
    };
    println!("{:?}", user1);
}

Struct fields follow the general rule of everything being private by default unless annotated with pub⮳.

/// Represents a user with their active status, username, and email.
#[derive(Debug)]
struct User {
    active: bool,
    username: String,
    email: String,
}

// It is common to define a function (or an associated function, see below) that
// initializes the struct:
fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username, /* Field init shorthand, instead of writing `username:
                   * username` */
        email, // Same
    }
}

fn main() {
    // We create an instance of the struct:
    let user1: User = build_user("user@example.com".into(), "user".to_string());

    // Then update the struct.
    // .. is used to fill in the rest
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1 /* The remaining fields not explicitly set will have the
                 * same value as the fields in the given instance. */
    };
    println!("{:?}", user2);
}
/// A tuple struct.
///
/// Note the ( ) and the lack of field names.
#[derive(Debug)]
struct Color(i32, i32, i32);

/// A unit-like struct.
///
/// Unit-like structs are useful when you need to implement a trait on
/// something, but don't have any data that you want to store in the type
/// itself.
#[derive(Debug)]
struct AlwaysEqual; // Note that there are no fields.

fn main() {
    let black = Color(0, 0, 0);
    println!("{black:?}");

    let s = AlwaysEqual;
    println!("{s:?}");
}
/// A struct representing a rectangle with a width and height.
struct Rectangle {
    width: u32,
    height: u32,
}

/// Implementation block (multiple blocks are allowed for a given struct).
impl Rectangle {
    /// Method: note the `self`:
    fn area(&self) -> u32 {
        // `&self` is short for `self: &Self`, an alias for the type that the
        // impl block is for.
        self.width * self.height
    }

    /// Associated Function.
    /// Note that there are NO `self`, `&self`, or `&mut self`.
    /// This is often used to define a "constructor": `SomeType::new(...)`.
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
}

fn main() {
    // Call the associated function.
    // Note the syntax: `<Type>::<function>`.
    let sq: Rectangle = Rectangle::square(5);
    // Call the method. Note the dot.
    // This is equivalent to `Rectangle::area(sq)`.
    println!("Area: {}", sq.area());
}