Using rust structs to structure related data

// to define a struct
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}
 
fn main() {
    // to create a new instance
    let mut user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
 
    // use dot to get/set a value from a struct
    // to set a value, the entire struct must be mutable
    user1.email = String::from("anotheremail@example.com");
 
    let user2 = build_user(
        String::from("someone@example.com"),
        String::from("someusername123"),
    );
 
    // creating instances from other instances
    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}
 
fn build_user(email: String, username: String) -> User {
    // shorthand syntax
    User {
        email,
        username,
        active: true,
        sign_in_count: 1,
    }
}

Tuple structs

fn main() {
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);
 
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
}

Unit-like structs without any fields

fn main() {
    // behave similarly to `()`
    // no need for `{` or `(`
    struct AlwaysEqual;
 
    let subject = AlwaysEqual;
}

Unit-like structs can be useful in situations in which you need to implement a trait on some type but don’t have any data that you want to store in the type itself.

Adding useful functionality with derived traits

// adding the `Debug` trait for debug formatting
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
 
fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
 
    println!("rect1 is {:?}", rect1);
}

dbg! macro

The dbg! macro takes ownership of an expression, prints the file and line number of where that dbg! macro call occurs in your code along with the resulting value of that expression, and returns ownership of the value. Calling the dbg! macro prints to the standard error console stream (stderr), as opposed to println! which prints to the standard output console stream (stdout).

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
 
fn main() {
    let scale = 2;
    let rect1 = Rectangle {
        width: dbg!(30 * scale),
        height: 50,
    };
 
    dbg!(&rect1);
}

Method syntax

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
 
impl Rectangle {
    // `&self` is short for `self: &Self`
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
 
fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
 
    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
 
impl Rectangle {
    // associated function
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}
 
// each struct is allowed to have multiple `impl` blocks
// useful especially when dealing with generic types and traits
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}
 
impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
fn main() {
    let sq = Rectangle::square(3);
}