https://doc.rust-lang.org/book/ch05-01-defining-structs.html

// Define

struct User {
    field1: <type>,
    field2: <type>,
    // ...
}

// Use:

fn main() {
    let user1 = User {field1: value1, 
                field2: value2,
                // ...
                }
}

// init fn
fn build_user(f1: <type>, f2: <type>, ...) -> User {
    User {
        field1: f1,
        field2: f2,
        // ...
    }
}

// Field Init shorthand: field names and parameter names are exactly the same

fn build_user(fleld1: <type>, fleld2: <type>, ...) -> User {
    User { field1, field2, ...}
}


// create instance from struct update (from another instance)

fn main() {
    // --snip--

    let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
}

methods

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    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()
    );
}

auto dereferencing
Rust doesn’t have an equivalent to the -> operator; instead, Rust has a feature called automatic referencing and dereferencing. Calling methods is one of the few places in Rust that has this behavior.

Here’s how it works: when you call a method with object.something(), Rust automatically adds in &, &mut, or * so object matches the signature of the method. In other words, the following are the same:

p1.distance(&p2);
(&p1).distance(&p2);