# Rust Programming Language

# Getting started

### Hello world

```rust
fn main() {
	println!("Hello, world!");
}
```

The main function is always the first function that is executed in every Rust program. The body of the function is wrapped in `{}`. `println!` call is actually not a function call, but rather is calling a Rust macro. The macro is denoted by the `!` at the end of the function. Statements are end with semi colons.

##### Compiling and running rust program

To compile a single `*.rs` file, you would run

```bash
rustc main.rs
```

The rust compiler will compile your code into a binary where then you can execute the binary by running:

```bash
./main
```

### Hello, cargo!

Cargo is rust's build system and package manager. Think of it as your build tool, like an automated Makefile that you don't have to write yourself. It will find and compile together all of the relevant rust files that you have written. It also serves as the package manager think of `npm` that let you download and use third party library that is written by other people.

If you are creating more than one rust files, then it would probably be a good idea to use cargo as your build tool and package manager. It is the de facto standard anyway.

##### Creating a project with cargo

To create a new project with cargo, run the following code, of course substitute the project name with what you want

```bash
cargo new hello_cargo
```

The project directory that is created with cargo will be initialize as a git repository for you automatically.

It also contain `Cargo.toml` which is used for managing dependencies used by your project.

`src` directory contains all of your rust source code.

##### Building and running cargo project

To build your cargo project run:

```bash
cargo build
```

This will create your executable file in *target/debug/&lt;executable\_name&gt;* but still in the same root directory. You can then run the executable the same way.

If you want to build and run your executable immediately you can issue the command:

```bash
cargo run
```

This will build then immediately run your executable after it has finished building.

If you want to check if your code can compile run

```
cargo check
```

To see if your code can be compiled or not.

##### Building for release

If you are going to release your code for production then you can run the command:

```bash
cargo build --release
```

This will compile your code with optimization, and the executable will be under `target/release` instead of `target/debug`.

# Variables, types, mutatbility, functions, and control flow

### Variables

By default variables are immutable in Rust. Once you assign a value to it you cannot change it without explicitly marking the variable as mutable.

```rust
fn main() {
  	let x = 5;
  	x = 6; // compiler error
}
```

In order to make your variable mutable you must mark it with the `mut` keyword before the variable name like so:

```rust
fn main() {
	let mut x = 5;
    println!("{x}");
    x = 6;
    println!("{x}");
}
```

##### Constants

To declare a constant variable, a variable that you cannot change, you use the `const` keyword. Constants must have its value annotated. Meaning you have to explicitly give it its data type otherwise, it will not work.

```rust
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
```

##### Shadowing

You are allowed to re-declare a variable of the same name. And the type of the variable can even be different, and this is referred to as shadowing.

```rust
fn main() {
	let x = 5;
  	let x = x + 1; // this is allowed
}
```

The final value of the variable `x` will be `6` because the `x` it is referring to in the assignment is still referring to the old variable, before it is updated as a new variable.

Shadowing is different than marking a variable as `mut` because the data type that you can reassign the data to can be completely different. In addition, if you don't use `let` and the variable isn't marked as `mut` then you will get a compile-time error. It isn't shadowing.

Shadowing is good if you want to reuse the same variable name after performing some transformation on the original value. For example

```rust
let spaces = "    ";
let spaces = spaces.len(); // This will update variable spaces to be the number of spaces
```

You cannot do this the data is mutable, because you cannot change the data type of the variable if it is marked as mutable. You can only change it to the value of the same type, not to a different type.

### Data types

In Rust every value has a data type, since Rust is a statically typed language so it will know how much memory to allocate for each piece of data that you use at compile time. Usually, the compiler can infer the type for simple assignments, but if there are many type that are possible, you must add a type annotation, to tell the compiler that this is the type for the data.

```rust
let guess: u32 = "42".parse().expect("Not a number");
```

In this case, you have to add the `unsigned 32-bit` integer annotation, otherwise, Rust will display an error since the compiler need more information about the type `guess` is.

##### Scalar types

Scalar type represents a single value, primitives per say. Integers, floating-point numbers, booleans, and characters are scalar type in Rust.

##### 1. Integer

An integer is a number without fractional component. There are many variant to an integer as listed below

<table border="1" id="bkmrk-length-signed-unsign" style="border-collapse: collapse; width: 100%;"><colgroup><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col><col style="width: 33.3333%;"></col></colgroup><tbody><tr><td>Length  
</td><td>Signed  
</td><td>Unsigned  
</td></tr><tr><td>8-bit  
</td><td>`i8`  
</td><td>`u8`  
</td></tr><tr><td>16-bit

</td><td>`i16`  
</td><td>`u16`</td></tr><tr><td>32bit  
</td><td>`i32`  
</td><td>`u32`  
</td></tr><tr><td>64-bit  
</td><td>`i64`</td><td>`u64`  
</td></tr><tr><td>128-bit  
</td><td>`i128`  
</td><td>`u126`</td></tr><tr><td>arch  
</td><td>`isize`  
</td><td>`usize`  
</td></tr></tbody></table>

Unsigned to remind you are only positive numbers, and they have the range from:

\[0, 2<sup>n</sup> - 1\]

Signed to remind you are numbers that can be negative, in Rust signed numbers are stored using two's complement representation so they have the range from:

\[-2<sup>(n - 1)</sup>, 2<sup>(n - 1)</sup> - 1\]

Arch type will depend on the architecture of your computer. If your computer is 64-bit, then arch is 64-bit, if your computer is 32-bit then arch is 32-bit.

You can write number in any base.

1. Decimal: Use `_` to serve as delimiter for a bigger number like `87_321` for 87,321
2. Hexadecimal: Prefix the hexadecimal number with `0x`
3. Octal: Prefix the octal number with `0o`
4. Binary: Prefix the binary with `0b`
5. Byte (u8 type): Prefix the byte with `b'<byte goes here>'`

Rust supporst all of the basic math operations that you would expect.

##### 2. Floating-point types  


There are two types of precision `f32` and `f64`. Default is `f64` for floating point, has more precision.

##### 3. Boolean type

Can have the two possible value `true` and `false`. Boolean are one byte in size, and in Rust is defined using the `bool` type.

##### 4. Character type

Character type holds four bytes of letter. You specify `char` literal with single quotes, not double quotes which denotes string literals. It is four bytes in size so it can represent lots more character than just ASCII, Chinese, Japanese, and Korean characters.

##### Compound types

You can group multiple values into one type, Rust have two primitive compound types, tuples and array.

##### Tuple type

General way fo grouping together a number of values with variety of types into one compound type.

Tuple has a fixed length, once they are declared, the size cannot grow or shrink.

You can create tuple by writing a comma-separated list of values inside parentheses. Every index in the tuple has a type and you can add the optional type annotation:

```rust
fn main() {
  	let tup: (i32, f64, u8) = (500, 6.4, 1);
  	let tup2 = (true, true, false);
}
```

To access the element inside the tuple according to their indices you would use the `.` accessor. For example:

```rust
fn main() {
    let x: (i32, f64, u8) = (500, 6.4, 1);

    let five_hundred = x.0;

    let six_point_four = x.1;

    let one = x.2;
}
```

You can also get the values out from the tuple by using a destructure assignment like so:

```rust
let tup (500, 6.4, 1);
let (x, y, z) = tup;

println!("The value of y is : {y});
```

##### Array type

You can declare an array by using comma-separated list inside square brackets:

```rust
let a = [1, 2, 3, 4, 5];
```

You can also write the array's type using square brackets with the type of each element, semicolon, and then the number of the elements in the array like so:

```rust
let a: [i32; 5] = [1, 2, 3, 4, 5];
```

You can access each array element by indexing into the indices like so:

```rust
let a = [1, 2, 3,];
let first = a[0];
let second = a[1];
```

Accessing an element out of bound will raise an runtime error, in the case of Rust, it will be an panic. The program terminates and exists with an error.

### Functions

Use snake case for function and variable name just like in Python.

To define a function in Rust you would use the `fn` keyword followed by the function name, then the parameters that are passed into the function.

Rust doesn't care where you define the function, as long as it is in the file you can use it even if it is defined after the place you defined the function.

##### Parameters

If your function takes parameter then you function header must have its type annotated.

##### Statements and expressions

Statements are code that are ran and do not contain a return value

Expressions on the other hand evaluates to a return value

Unlike Ruby, assignment in Rust is a statement not an expression, meaning you cannot do something like:

```rust
let x = (let y = 6);
```

The `let` statement does not return 6, but in Ruby it does, which also make `x` equal to 6. But in Rust this will result in compilation error.

##### Return value

Functions can also return values, you do not name the return value, but you have to declare their type after an arrow like so

```rust
fn five() -> i32 {
	5
}

fn main() {
  	let x = five();
  	println!("The value is {x}");
}
```

In this case the function `five` returns the integer value 5.

Return value can be explicitly done by using the `return` keyword, or the return value can be implicit if the returned value is the last expression in the function, so you do not include the semicolon, if that expression is the last expression in the function that you want to return. If you include a semicolon to the expression then it will become a statement and therefore that value is not returned.

```rust
fn foo() -> i32 {
	return 3;
}

// Or you can do
fn foo() -> i32 {
	3   // do not include semicolon! Then it will not be returning it! and will be an error
}
```

### Comments

Comments can be done via `//` there is no C style comments in Rust.

### Control flow

##### if expressions

```rust
let number = 3;

if number < 5 {
	println!("Condition is met");
}
else if number == 6 {
	println("Condition exactly met");
}
else {
	println!("Condition isn't met");
}
```

You can use if statement within a let statement to do conditional assignments

```rust
let condition = true;
let number = if condition { 5 } else { 6 };
```

If the condition is true, then it will assign 5 to variable `number`, if false then it will assign 6. In addition, the type that the if statement evaluate to must be the type type, which means this is wrong:

```rust
let condition = true;
let number = if condition { 5 } else { "six" };
```

This will result in compiler error because the of the if statement branch don't match. One is an integer the other is a string!

##### While loops

```rust
let mut number = 3;

while number != 0 {
	println!("The number is {number}");
    number -= 1;
}
```

##### For loop

You can use a for loop to loop through each element of an array:

```rust
let a = [1, 2, 3, 4, 5, 6];
for num in a {
	println!("Value is {num}");
}
```

Range with for loop, `Range` can be denoted using `start..end` to generate a sequence of number without including `end`:

```rust
for number in (1..4) {
	println!("{number}");
}
```

# References and Borrowing

### Ownership

Rust has it's own way of managing memories that are allocated on the heap. Unlike C, where the burden of allocating and freeing the memory that is allocated on the heap falls on the shoulder of the programmer, Rust manages the memory for you as long as you follow it's ownership conventions.

This is how Rust deal with dynamically allocated memory on the heap. When you allocate data on the heap, that piece of data will be associated with a variable name. When the scope of that variable ends, and naturally (most of the time) the data on the heap associated with that variable will need to be freed, and Rust does that for you automatically:

```rust
{
	let s = String::from("Hello"); // s is valid from this point forward
}	// Scope of s is over, s is no longer valid, and the memory is returned to the allocator
```

Whenever a variable goes out of scope, if it has its memory allocated on the heap, it will be called a special function called `drop` when the variable goes out of scope. **It will free the memory that is allocated for that variable back to the allocator, Rust will call it for you automatically at the closing curly bracket (the end of a scope).**

##### Data move

Let's look at some form of alias and copying in Rust:

```rust
let x = 5;
let y = x;
```

This will do what you expect, the value of `x` is copied over to `y`. If you change `y` it will not affect the value of `x`.

Now let's look at data allocated on the heap.

```rust
let s1 = String::from("Hello");
let s2 = s1;
```

If we do this, we assume that `s2` is an alias which points to the same string that's allocated on the heap. That will be true for language that C or Python, but in Rust it is different. When you make an alias to another data allocated on the heap, that pointer will be moved from `s1` to `s2`, so `s1` will no longer be valid after line number 2! This is due to the design of Rust because like we have mentioned earlier, when a variable goes out of scope a special `drop` function is called to free up the memory allocated for the data, if there is two variables that points to that allocated data, then there is going to be a double free error!

To resolve this, Rust does variable move, so when you do `s2 = s1`, `s1` will no longer be valid afterward, so Rust only needs to worry about freeing up `s2` and doesn't have to worry about freeing `s1` anymore.

This is called move, Rust will invalidate the first variable after you do the assignment.![Three tables: tables s1 and s2 representing those strings on the
stack, respectively, and both pointing to the same string data on the heap.](https://doc.rust-lang.org/book/img/trpl04-02.svg)This is wrong!

##### Clone

However, if you want to clone the data allocated on the heap you can call the `clone` method.

```rust
let s1 = String::from("hello");
let s2 = s1.clone();
```

Now `s2` will also contain a copy of the heap data pointed by `s1`.

##### What about variable on the stack?

If you use say primitives in Rust like an integer like so

```rust
let x = 5;
let y = x;
```

Both `x, y` are still valid after running line number 2, why? This is because primitive's data size like integer is known at compile time and are stored entirely on the stack, copying the actual value are quick and easy to make, so there is no reason to invalidate `x` afterward.

##### Function and ownership

If you decide to pass a variable data that's allocated on the heap to a function let's say, it will also carry out move, which means the variable that you pass into the function will no longer be valid after you do the function call like so:

```rust
fn main() {
	let s = String::from("hello");
    
    take(s); // s is no longer validate after
    
    let x = 5;
    
    cant_take(x); // x is still valid because it is a copy, not a move
}

fn take(input: String) {
	// do something
}

fn cant_take(num: i32) {
	// do something
}
```

### References and borrowing  


So to solve what we have just talked about, instead of moving the variable into the function, we will give the function a reference to the variable, so that after the function call the variable with data allocated on the heap is still valid afterward.

<p class="callout info">References uses the ampersand syntax, note this is not getting back the pointer, although, references are implemented via pointer, this is different than saying &amp;num in C, which get you the pointer that points to the number.</p>

```rust
fn main() {
	let s1 = String::from("hello");
    
    let len = calculate(&s1);
    
    println("{}'s length is {}", s1, len);
}

fn calculate(s: &String) -> usize {
	s.len()
}
```

In this case, in order to pass a reference of a variable, we have to change the parameter type of the function from `String` to `&String` to denote that the parameter is indeed a reference to a String. This is called borrowing, it is borrowing the reference without moving it.

Now `s` will be a reference, which points to the same data that `s1` points to.

##### Mutable references  


If you want to say append any data to the reference that is passed to a function, you have to add the mutable modifier otherwise, the reference would not be able to make any changes to the data on the heap.

```rust
fn main() {
    let s = String::from("hello");

    change(&s);
}

fn change(some_string: &String) {
    some_string.push_str(", world"); // This will not work!
}
```

After adding `mut` modifier to both of the variable and the function header to signal that this function will change the String then it will work properly:

```rust
fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}
```

When you are doing mutable borrowing you can only do so when there is no other references to that same value:

```rust
let mut s = String::from("hello");

let r1 = &mut s;
let r2 = &mut s; // second mutable borrow occurred, doesn't work
```

In this case `r2` is a second mutable borrower, but there is already a mutable borrower that existed already, hence the code will not compile.

**In addition, if you are creating mutable references you cannot fix it with immutable references:**

```rust
let mut s = String::from("hello");

let r1 = &s; // no problem
let r2 = &s; // a second immutable reference is fine
let r3 = &mut s; // error mixing immutable and mutable references
```

However, if you finish using a reference, (the scope of a reference starts from where it was introduced and continue through the last time that reference is used), then you can introduce say a mutable reference.

```rust
let mut s = String::from("hello");

let r1 = &s; // fine
let r2 = &s; // both immutable reference so is okay

println!("{} {}", r1, r2); // using the two immutable references, so their scope ends here

let r3 = &mut s; // introducing a mutable reference, it is okay because immutable references ended the line before
println("{}", r3);
```

##### Dangling reference  


If you are creating a local variable in a function, and then you attempt to return a reference to that variable from that function, Rust will prevent you from doing that because the data will be invalidated after the function is finished.

To resolve that problem, instead of returning a reference, return that variable directly, this will result in a move which won't deallocate that local variable if it is a move. However, if you return a reference, the local variable will be deallocated and that reference will become invalid. (In C you can return a pointer to a local variable after the function is finished, but dereferencing it will resulting in undefined behavior).

# Slice Type

### Slice type

Slices in Rust let you reference a contiguous sequence of elements in a collection rather than referencing the whole collection.

It is also a reference so there is no ownership, no moving.

Let's start with a string slice that reference to a part of a String:

```rust
let s = String::from("hello world");

let hello = &s[0..5];
let world = &s[6.11];
```

To create a slice you specify the collection you are creating the slice reference from along with the `&` to indicate that it is an reference. Then you provide the range `[starting_index..ending_index]`, `starting_index` is the first position in the slice and `ending_index` is the ending element index, excluding that element.

##### Why slice?

The reason why we are using slice because say we are finding a particular index in a String, after finding that index number, that String suddenly changed, but you still used the old index number that isn't valid anymore, this will result in a code bug. However, using slice type, your compiler will ensure that the index number or particular information you retrieve about that String remains valid before it is changed.

```rust
let mut s = String::from("hello world");

let word = first_word(&s); // get the reference to "hello" in s

s.clear(); // error, because we are using mutable reference here, but there is a immutable reference existing!

println!("the first word is {}", word);
```

Thus using slice type will prevent any mutable changes from happening before the slice type gets used.

### String literals

```rust
let s = "hello world";
```

The type of `s` here is `&str`, a slice that points to that string literal in binary. It is also immutable because there is no `mut` modifier.

##### Using string slice as parameters

By making the parameter of a string from

```rust
fn first_word(s: &String) -> &str
```

Into to

```rust
fn first_word(s: &str) -> &str
```

We are able to take slices of String whether partial or whole, or on the entire reference, because slice type are reference themselves.

We can also slice type string literal, because string literal themselves are also string slices you can also pass them in directly, or you can slice them too.

```rust
fn main() {
    let my_string = String::from("hello world");

    // `first_word` works on slices of `String`s, whether partial or whole
    let word = first_word(&my_string[0..6]);
    let word = first_word(&my_string[..]);
    // `first_word` also works on references to `String`s, which are equivalent
    // to whole slices of `String`s
    let word = first_word(&my_string);

    let my_string_literal = "hello world";

    // `first_word` works on slices of string literals, whether partial or whole
    let word = first_word(&my_string_literal[0..6]);
    let word = first_word(&my_string_literal[..]);

    // Because string literals *are* string slices already,
    // this works too, without the slice syntax!
    let word = first_word(my_string_literal);
}
```

# 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.

# Enum and Pattern Matching

### Defining an Enum

Enum or enumeration gives you a way of defining a set of possible values for one value. "This value can be these possible set of values".

To define an enum to be a set of possible values here is an example:

```rust
enum IpAddrKind {
	V4,
    V6,
}
```

Here, the enum `IpAddrKind` is a custom data type that can have two possible values, V4 and V6. After defining this enum you can use it elsewhere in your code.

To define an enum with one of its variations you would use the `::` syntax under the enum name like such:

```rust
let four = IpAdddrKind::V4;
let six = IpAddrKind::V6;
```

##### Function taking enum

You can also then use enum as a function parameter:

```rust
fn route(ip_kind: IpAddrKind) {}

// invoking it
route(IpAddrKind::V4);
route(IpAddrKind::V6);
```

##### Advantage of enum over struct

Using enum you can actually give an associated data with each possible variations. You can give say `V4` three `u32` and for `V6` a String value like such:

```rust
enum IpAddr {
	V4(u32, u32, u32),
    V6(String),
}
```

Doing it this way, you do not need to make extra struct to associate data with each of the enum variations.

The associated data for each enum variant can be anything: strings, numeric types, or even structs!

To actually give the value when creating it you would do something like so:

```rust
 enum IpAddr {
        V4(u8, u8, u8, u8),
        V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
```

##### Enum examples

```rust
enum Message {
	Quit,
    Move {x: i32, y: i32},
    Write(String),
    ChangeColor(i32, i32, i32),
}
```

In this case there are four variants of the Message enum

1. Quit: Has no associated data
2. Move: has named fields just like a struct
3. Write: Has a single String
4. ChangeColor: Has three `i32` values

##### Methods on Enum

Rememberthat the `impl` block work on structs and also enums. So you can define methods for each enum type that you have defined:

```rust
impl Message {
	fn call(&self) {
    	// method body
	}
}

let m = Message::write(String::from("hello"));
m.call();
```

You can call it on the enum variant that you have defined just like how you can call it on an instance of a struct.

### The match control flow construct

To actually retrieve the associated value out from the enum variant and do conditional with it you would have to use the `match` construct.

You would be able to use the `match` construct to compare a value against a series of patterns then execute code based on which pattern it is matched.

`match` not only work with enum types but literal values, variable names, wildcards, and other things as well!

##### Testing match with enum

```rust
enum Coin {
	Penny,
    Nickle,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
  	match coin {
      	Coin::Penny => 1,
      	Coin::Nickle => 5,
      	Coin::Dime => 10,
      	Coin::Quarter => 25,
  	}
}
```

The function `value_in_cents` will take in an enum of Coin type and then return it's corresponding variant value in `u8`.

To use the `match` expression, you would have to use the match keyword follow by the value that you want to pattern match, then you would list out all the possible combination of pattern that you are matching for this particular value.

The match arms have two parts, the pattern and some code, if the code is short and one line long, then you don't need another set of brackets, however, if you have multiple lines of code to execute if the pattern matches then you would need the brackets. The pattern and code is separated by the `=>` operator.

When `match` expression executes, it compares the value against the pattern of each arm in order, if it matches then that code is executed.

##### Pattern with associated values

To retrieve the value for a corresponding enum variant you can follow the same syntax like so:

```rust
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(bool),
}
```

In this case, we have a enum variant Quarter with an associated value of `bool` to indicate whether it is rare or not. If we are going to write a function to retrieve that `bool` value from the Quarter variant, how would we do that?

```rust
fn retrieve_rare(coin: Coin) -> bool {
	match coin {
    	Coin::Quarter(rare) => rare,
        other => false,
	}
}
```

Now if we are calling the function like so `retrieve_rare(Coin::Quarter(true))` this will yield `true` as it's return value. How does it work? Well, we are constructing a Quarter variant of `Coin` enum with `true` as it's associated data to indicate that it is indeed rare. Then when that enum type is passed into the function it will be doing a pattern match, it matches the first pattern because it is a Quarter, the associated data is binded to the variable `rare`, and then we are just simply return `rare` as it is because we just want to get that value out from the enum.

<p class="callout info">Matches must be exhaustive, it must cover all possibilities. If is missing some possibility then the code will not compile!  
</p>

##### Catch-all pattern

If you are only interested in say two out of ten possible patterns and want to handle the rest of the pattern one way, you don't have to code out all of the pattern matches, and instead use a catch-all pattern.

```rust
let dice_roll = 9;
match dice_roll {
	3 => add_fancy_hat(),
    7 => remove_fancy_hat(),
    other => move_player(other),
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}
```

As you can see, the `other` arm at the end will be a catch-all pattern that handles all other patterns that is not 3 and 7. The value of all the none matched pattern are stored into `other`.

If we do not need the value, and just need to catch-all then you can use the pattern `_` to do the catch-all. Otherwise, if you don't use the value in catch-all Rust will warn you about unused variable.

### `if let` control flow

Combining if and let let you handle values that match one pattern while ignoring the rest. For example:

```rust
let config_max = Some(3);
match config_max {
	Some(max) => println!("The max is {}", max),
    _ => (),
}
```

This code will print out the value inside the enum `Some` and for any other variant it will do nothing (i.e. for the `None` variant it will do nothing).

However, writing `_` everytime and writing these verbose pattern matching for just doing something small for one pattern is just too repetitive, so `if let` let you condense this into much shorter syntax:

```rust
let config_max = Some(3);
if let Some(max) = config_max {
	println!("The max is {}", max);
}
```

This is equivalent to the `match` expression done previously but now you don't have to write the `_` catch-all pattern and just focus on the one case you actually care. It works the same way as a `match` expression, it will bind the value inside `Some` to `max` variable if `config_max` is a `Some` enum variant.

You can also include an `else` with `if let` syntax. Which is the same as the things inside `_` the catch-all pattern:

```rust
let mut count = 0;
if let Coin::Quarter(state) = coin {
	println!("The state is {}", state);
}
else {
	count += 1;
}
```

This code will increment `count` if the Coin enum isn't an Quarter variant.

<p class="callout info">Generally, use `if let` if you are only expecting to handle one of the enum variant and ignoring the rest.</p>

# Packages, Crates, and Modules

### Crate

The smallest unit that the Rust compiler will work with. When you run `rustc some_file.rs` the file `some_file.rs` is treated as a crate file.

A crate when being compiled can be compiled into two forms, a binary crate or a library crate. Binary crate are programs that after being compiled are turned into an executable that you can run. Binary crate must have a function called `main` that gets called when the executable is ran.

Library crate don't have a `main` function and they do not get compiled into an executable binary. Instead, they defined functions that are meant to be shared with multiple projects, much like exporting some common functions that you are going to be using in other projects.

Hence in Rust, when you refer to "crates" it is usually library crate, and refer to binary crate as just the executable or binary.

##### Exporting and importing functionality

We will go through how Rust does it's import and export system via an example, assume we have a directory setup as such:

```
my_project
├── Cargo.toml
└─┬ src
  ├── main.rs
  ├── config.rs
  ├─┬ routes
  │ ├── health_route.rs
  │ └── user_route.rs
  └─┬ models
    └── user_model.rs
```

We have functions written in `config.rs, routes/health_route.rs, routes/user_route.rs, and modules/user_module.rs` that we want our `main.rs` use. How do we do that?

##### Importing `config.rs`

Rust does not build the module tree for you even though the files with functions that you want your `main.rs` to use is under the same directory, Rust by default only sees the crate module which is `main.rs`.

[![image.png](https://wiki.tamarinne.me/uploads/images/gallery/2023-01/scaled-1680-/ZQIimage.png)](https://wiki.tamarine.me/uploads/images/gallery/2023-01/ZQIimage.png)

So what do we do? We will have to explicitly build the module tree in Rust, there is no implicit mapping between the directory tree and the module tree!

In order to add files to the module tree we have to declare that file as a submodule using the `mod` keyword. Where do you declare submodule? Where you are using file, in this case we want to call those functions in `main.rs` hence you will have to declare the submodule in `main.rs` by writing `mod my_module;`.

By writing `mod my_module` the compiler will look for `my_module.rs` or `my_module/mod.rs` in the same directory.

In this case because we are importing `config.rs` which is a file in the same directory as `main.rs` you can just write `mod config;`

```rust
// main.rs
mod config;

fn main() {
  config::print_config();
  println!("main");
}
```

After you import the module the functions can be called by referring to them using `::` under the submodule namespace.

After you have declare the submodule the module tree looks something like this:

[![image.png](https://wiki.tamarinne.me/uploads/images/gallery/2023-01/scaled-1680-/Axfimage.png)](https://wiki.tamarine.me/uploads/images/gallery/2023-01/Axfimage.png)

##### But wait it still doesn't work?!

After you have successful declare the `config` module, it isn't enough to call the function because almost everything in Rust is private by default. In order to call `print_config` you have to mark it as a public function that other file can call by using the `pub` keyword.

```rust
// config.rs
pub fn print_config() {
  println!("config");
}
```

Now you will be able to run `main.rs` without a problem.

##### Importing `routes/health_route.rs`

Now here we are importing another file under another directory the `routes` directory. The `mod` keyword is only for `my_module.rs or my_module/mod.rs` in the same directory. In order to call functions inside `routes/health_route.rs` from `main.rs` here are the things we need to do

1. Make a file named `routes/mod.rs`
2. Declare the `routes` submodule in `main.rs`, this will import the file `routes/mod.rs`
3. Then in `routes/mod.rs` we will declare the submodule `health_route` and make it public by prefixing it with `pub` keyword
4. Then in addition we also have to make the function inside `health_routes.rs` public as well and we are finally done

```c#
my_project
├── Cargo.toml
└─┬ src
  ├── main.rs
  ├── config.rs
  ├─┬ routes
  │ ├── mod.rs
  │ ├── health_route.rs
  │ └── user_route.rs
  └─┬ models
    └── user_model.rs
```

```rust
// main.rs
mod config;
mod routes;

fn main() {
  routes::health_route::print_health_route();
  config::print_config();
  println!("main");
}
```

```rust
// routes/mod.rs
pub mod health_route;
```

```rust
// routes/health_route.rs
pub fn print_health_route() {
  println!("health_route");
}
```

<p class="callout info">The idea is that if you are going to declare a submodule under another directory, you will import a submodule that has the same directory name. i.e. `another_directory/mod.rs`, and inside that file you will declare the public submodule that you are declaring. Finally make the function of the nested submodule you want to export public as well.</p>

When you call it, you will have to go by the submodule names you have set up including the directory name submodule.

# Common Collections

### Vector

Allows you to store variable number of values next to each other

To create an empty vector you call the `Vec::new` function

```rust
let v: Vec<i32> = Vec::new();
```

Since we are not inserting any initial values into the vector we will have to provide type annotations otherwise Rust doesn't know what type of vector this is for. There is the `vec!` macro that will create a new vector that holds the values you give it:

```rust
let v = vec![1, 2, 3];
```

So you would rarely need to do the type annotation yourself.

##### Updating a vector

To add elements to the vector you would use the `push` method:

```rust
let mut v = Vec::new();

v.push(5);
v.push(6);
```

##### Reading elements of vectors

Two ways of getting elements out of the vector, via indexing or using the `get` method.

```rust
let v = vec![1, 2, 3, 4, 5];

let ele = third: &i32 = &v[2]; // indexing
let ele: Option<&i32> = v.get(2); // get method

match ele {
	Some(num) => println!("The number is {num}"),
  	None => println!("It doesn't exist"),
}
```

##### Iterating over a vector

This is with immutable reference

```rust
let v = vec![100, 32, 57];
for i in &v {
	println!("{i}"};
}
```

This is with mutable reference, in order to change the value of that mutable referene you have to use `*` dereference operator to get the value in `i` before the `+=` operator.

```rust
let mut v = vec![100, 32, 57];
for i in &mut v {
	*i += 50;
}
```

### String

A collection of characters, they are stored on the heap. This is different than String literals which is `str` or `&str` slice type.

### Hash map

Allows you to associate a value with a key.