# Using Structs to Structure Related Data

### Defining and instantiating structs

Struct allows you to compose different type of data together into one big object, just like structs in C.

You will have to name each piece of data that you are using so that you can access them when you instantiate a struct later.

Here is how to define a sample struct (Note you would write this outside of functions):

```rust
struct User {
	active: bool,
    username: String,
    email: String,
}
```

Then to instantiate a struct:

```rust
fn main() {
	let user1 = User {
    	active: true,
        username: String::from("Ricky"),
        email: String::from("irebo@gmail.com"),
	};
}
```

To access the fields that you have instantiated you would use the dot notation, `user1.active, user1.username, user1.email`.

To make the struct mutable you would also attach the `mut` modifier to the variable. The entire instance of struct must be mutable, Rust doesn't allow partial field mutability.

### Field init shorthand

Say you have a function that builds your struct and return it as its return value depending on the parameter you passed:

```rust
fn build_user(email: String, username: String) -> User {
	User {
    	active: true,
        username: username,
        email: email,
	}
}
```

Writing it like this will get repetitive, especially if there are going to be lot of parameter, instead you can use a shorthand, just ignore the key if the parameter that you passed into the function is the same as the key name:

```rust
fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
    }
}
```

This is much more concise without the repetition.

##### Creating instances from other instances with struct update syntax

Sometimes you might want to create a new instances from the old instances, changing some of the old values but keep the rest the same.

You can do it the hard coded way like such:

```rust
fn main() {
	// created user1 here
    
    let user2 = User {
    	active: user1.active,
        username: user1.username,
        email: String::from("new email@gmail.com"),
	};
}
```

This works but you have to type out all of the fields that are repeated, a much shorter way to do this is to use struct update syntax:

```rust
fn main() {
	// create user1 here
    
    let user2 = User {
    	email: String::from("new email here"),
        ..user1
	}
}
```

With this syntax, you only have to worry about writing the new value for the new instance, and leave all of the old values to struct update syntax to handle.

`..user1` must come last to specify that any remaining fields should be getting their values from the corresponding fields in `user1`.

<p class="callout danger">struct update syntax uses `=` like an assignment, so it will be moving data. After doing struct update you can no longer use `user1` as a whole after creating `user2` since data like `username` is moved to `user2` and not copied!</p>

##### Tuple struct

You can also create a tuple struct, which is like struct but doesn't have names associated with their fields, they only have type of the fields.

This is useful if you just want to give a simple tuple a name. And separate different type of tuple from each other.

```rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

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

You can access the tuple using the same tuple syntax, `tuple.<index number>`

### Method syntax  


Methods are like function but they are defined in the context of a struct, enum, or a trait object.

The first parameter of a method is always self, which represents the instance of the struct that the method is called on.

##### Defining methods

```rust
struct Rectangle {
	width: u32,
    height: u32,
}

impl Rectangle {
	fn area(&self) -> u32 {
    	self.width * self.height
	}
}

fn main() {
	let r1 = Rectangle {
    	width: 30,
        height: 50,
	};
    
    println!("The area is {}", r1.area());
}
```

To define function in the context of in this case a struct, you write the `impl` block for `Rectangle`. Everything inside this `impl` block will be associated with the `Rectangle` type. Then you can write the method itself, making sure that the first parameter is a reference to `self`.

Then you can call the method on the object.

The first parameter must be `&self` and is actually a shorthand for `self: &Self`, `Self` type itself is an alias for the type that the `impl` block is for. This is so that we don't have to write `rectangle: &Rectangle` instead.

Method can take ownership of `self`, borrow self immutable or mutably. In the example, it is just borrowing self immutably since it is just reading data.

<p class="callout info">Just for your information, no matter which `self` you do, taking ownership or do borrowing, Rust will automatically add the appropriate `&, &mut, or *` for you automatically. This is so that you can just focus on calling the method on the object without worrying about anything else  
</p>

```rust
p1.ditance(&p2);
// vs
(&p1).distance(&p2);
```

##### Associated functions

Functions implemented with `impl` block are called assocaited functions because they are connected to the type of struct they are defined. You are able to define associated functions that don't have `self` as first parameter (hence they are no longer methods) they are reference to as static or class methods. They are associated with the type rather than an instance.

Associated functions that don't have `self` are often used for constructors that return new instance of the struct, just like `String::from`.

```rust
impl Rectangle {
	fn square(size: u32) -> Self {
    	Self {
        	width: size,
            height: size,
		}
	}
}
```

<p class="callout info">`Self` in this case is an alias for the type that appears after the `impl` keyword, `Rectangle` in this case.</p>

Then to call associated functions that doesn't take `self` as first parameter you use the `::` syntax with the struct name like such:

```rust
let sq = Rectangle::square(3);
```

##### Multiple impl block  


You can separate different methods into `impl` blocks, although there is really no reason to unless for readability.

```rust
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
    }
}
```

This is perfectly valid syntax.