# Data Types

## Constants

constants can be delared anywhere, convension to use all caps in const
need const keyword, not always eval at compile time
variables can only be assigned once (needs mut to assign more than once (need to be same type))

```rust
const SECONDS_PER_HOUR: i32 = 60 * 60;
```

## Variables

variables are immuatable by default
variables can be inferred but sometimes needs explicit typing
    
```rust
    let foo = 5;
```
need to add mut keyword to enable rewriting, generally avoid unless actually used

```rust
    let mut bar = 6;
```

# SHADOWING

#### Cannot have mutable shadows

allows for reuse of namespace instead of spaces_str and spaces_num
```rust
    let spaces = " _ _ ";
    let spaces = spaces.len();
    // will output 5 instead of " _ _ " beacuse that is how long it is
    // the shadow of spaces (first) wont be printed until the overshadow of spaces goes out of scope
    println!("{spaces}"); // output: 5
```

not allowed shadow
```rust
    let mut spaces = " _ _ ";
    spaces = spaces.len();
```
cannot change type of variable once declared

# Primitive Data Types

## Scalars

### Integers

u is for usigned integers
i is for signed integers

number indicated how many bits it takes in memory
```rust    
    let z: i8;      // takes up 8 bits, can store values from -128 to 127
    let c: i16;     // takes up 16 bits
    let d: i32;     // takes up 32 bits (default for integers)
    let e: i64;     // takes up 64 bits
    let f: i128;    // takes up 128 bits
    let g: isize;   // takes up x bits, depends on the system's architecture/cpu

    let h: u8;      // takes up 8 bits, unsigned version (only positive)
                    // can store values from 0 to 255
```

#### Integer Overflow
will reset to the lowest value ie i8 129 -> -126
```rust 
    let example_over_flow: i8 = 129;
```

behavor only in production mode
dev mode will cause a panic and error out/tell you

### Floats
better to use double point due to modern cpus where there is not much difference in speed

#### Single Point Float
takes up 32 bits
```rust
    let a: f32 = 4.0;
```

#### Double Point Float
takes up 64 bits
```rust
    let b: f64 = 2.01;
```

#### Integers Represented Differently
can represent values in hex, oct, bin or dec
can hover with rust-analyzer extension to see value in dec

##### Dec with Reading Aid
value stored 1000
_ used to make easier to read
```rust
    let i = 1_000;
```

##### Hexidecimal
value stored 255
```rust
    let j = 0xff;
```

##### Octal
value stored 63
```rust
    let k = 0o77; 
```

##### Binary
value stored 13
```rust
    let l = 0b1101;
```

##### Bytes
u8 only
value stored 0x41 or 65
```rust
    let m = b'A';
```

## Numeric Operators / Basic Math
Numbers for reference
```rust
    let x: i16 = 8;
    let y: i16 = 5;
```

### Addition
```rust
    let sum  = x + y; // result: 13
```

### Subtraction
```rust
    let difference = x - y; //result: 3
```

### Multiplication
```rust
    let product: i16;
    product = x * y;
```

### Division
```rust    
    let quotent = 45.1 / 54.2;
    let truncated = x / y; // results in 1 (always rounds down)
```

### Remainder
```rust
    let remainder = x % y;
```

### Booleans
must be explicity typed to true or false
0 or 1 not allowed even with let var: bool
```rust
    let n = false;
    let o = true;
```

### Char
must use single quotes and not "" otherwise will be inferred as string literal
is stored as Unicode Scalar Value allowing for emoji, japanse char and other languages not supported by ASCII
takes 4 bytes in size or 32 bits
```rust
    let p = 'a';
```

## Compound Types
multiple values into one type

### Tuple
A general way of grouping multiple a number of values into one compound type
types do not need to be the same in every position

```rust
    let tup: (i32, f64, u8) = (500, 6.4, 1);
```
The variable tup has values written to it at initialization but it is not requried, order does not matter
similar to a struct in c

Vaules must be destructed out of a tuple to be accessed inidivually, can use a pattern matching to the tuple

```rust
 let (q, r, s) = tup;
```

This is called destructing becasue it breaks it into 3 parts

Can also be accessed with a .

***INDEX STARTS AT 0***
```rust
    let t = tup.0;  // t = 500
    let u = tup.1;  // u = 6.4
    let v = tup.2;  // v = 1
```

#### A Unit

This is a special value where a tuple has no values
```rust
    let w: () = ();
```
This represents an empty type or an empty return type

Expressions will implicitly return a unit if they dont return anything else

### Array

A collection of multiple values
Must have every value be the same type, cannot mix and match
Arrays must be a fixed length at initialization
useful when you want a set number of values or is static

Values are in [] and seperated by ,

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

Array located in stack same with above types

If you need your array/list to grow or shrink use a vector
If unsure weather to use an Array or Vector pick a vector

Times where using an array is better
```rust
let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
```

Accessing items in an array
```rust
    let ya = xa[0]; //value is 1
```

Initializing an Array
```rust
    let za: [i32; 5];   // allows for 5 32 bit signed integers inside
    let aa = [i8; 6];   // allow for 6 8 bit signed integers inside
```

Invalid Array Elements

```rust
use std::io;
fn main() {
    let a = [1, 2, 3, 4, 5];

    // Input of a number
    println!("Please enter an array index.");
    let mut index = String::new();
    io::stdin()
        .read_line(&mut index)
        .expect("Failed to read line");

    // change into a integer
    let index: usize = index
        .trim()
        .parse()
        .expect("Index entered was not a number");

    // access elemetn in array
    let element = a[index];
    println!("The value of the element at index {index} is: {element}");
}
```
this program would compile with not problems
for example inputting 7 into the program
this would cause a runtime error
the program would output an error because it didnt get to the final line println! before exiting 
it casue the program to exit before attempting to access the invalid space
this is a form of safe memory management that rust name

# Complex Data Type

## String Literal

This is a string literal it is hardcoded into a program
Always immutable
Fast and efficient, stored on the stack, property of being immuatable not of any real value
```rust
    let s: &str = "hello";
```

## String

This is a string that is stored on the heap, this can store data unkown (size, char, etc) to you at compile time
Can be mutable, but must request space on the heap then return that memory to the heap, will be returned as soon as it is no longer valid (it calls the drop method from String) 
not as fast and efficient
Example of a string being created form a string literal
```rust
    let ab:String = String::from("hello");
```

String concatinization example
```rust
    let mut s = String::from("hello");
    s.push_str(", world!"); // push_str() appends a literal to a String
    println!("{s}"); // This will print `hello, world!`
```


# Structures
Custom data type that packages up multiple data types into a meaningful manner and call the collection something
More similar to an object, can define related methods to them

Similar to tuples but have to name and define everything inside a struct, like a dictionary but with set names and order
Dont need to know order just know key
## Defining
Need ``struct`` keywork then name of struct, which should describe the significance of the gropued data
All values are seperated by commas these are called fields
general definition of the type created
```rust

struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,

}
```
## Initiating
To use give a owning var name thne concretely define what each value is
define the key: vaule pairs
dont need to initate in the same order they were defined in

```rust
    let mut user1 = User {
            active: true,
            username: String::from("someusername123"),
            email: String::from("someone@example.com"),
            sign_in_count: 1,
    };
```
to access values from the struct the ``dot``notation is used
note the WHOLE struct must be mutable, rust does not allow for partial mutability
```rust
    // user1 email field now is equal to the string example@mail.com
    user1.email = String::from("example@mail.com");
```
Can build a struct with implicit values input by default

```rust
fn build_user (email: String, username: String) {
    User {
        active: true,
        email: email,
        username: username,
        sign_in_count: 1,
    }
}
```
### Init Field Shorthand
This is useful when the param and the struct definition share the same name.
This reduces the amount of time spent on repeating key:value pairs
```rust
fn build_user(email: String, username: String) -> User {
    User {
        active: true,
        username,
        email,
        sign_in_count: 1,
    }
}
```

Only works beacuse param share same name as field key
this is equivalent to ```username:username or email:email```

### Creating Instances from Other Instances with Struct Update Syntax
Often useful to do so, only need to change 1 value

Slow method
```rust
    let user2 = User {
        active: user1.active,
        username: user1.username,
        email: String::from("another@emial.com"),
        sign_in_count: user.sign_in_count,
    };
```
Using Update syntax ``..`` this can be done a LOT Quicker

```rust
    let user2 = User {
        email: String::from("another@email.com"),
        ..user1
    }
    // user1 no longer completely valid
    // can still use user1.email, .active and .sign_in_count
```

This specifies htat the fields not explicity set should be the same as the given instance
This uses the = assignment operator and therefore a ownership move occurs with the ../update syntax

user1 would still be valid if both of the String types in were given new values

## Tuple Structs

This is also allowed but not key:value pairs
This still holds values in the field

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

    let black = RGBColour(0, 0, 0);
    let origin = Point(0, 0, 0);
```