triston-notes/Cards/dev/Rust Udemy Notes.md
2023-10-21 18:52:54 -05:00

255 lines
7.4 KiB
Markdown

up:: [[Rust]]
tags::
## Rust Notes
### Rust is a modern systems programming language with:
- memory safety (no garbage collection)
- no null values
- no exceptions
- modern package manager and build system (similar to npm)
- no data races (race conditions)
---
### Installing rust
#### on macos/linux
after running command follow onscreen instructions
```Bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
to confirm installation success run the following:
```Bash
-> rustc --version
rustc 1.67.1 (d5a82bbd2 2023-02-07)
-> cargo --version
cargo 1.67.1 (8ecd4f20a 2023-01-10)
-> rustup --version
rustup 1.25.2 (17db695f1 2023-02-01)
```
#### in VSCode
install rust-analyzer extension
---
### Exploring Cargo
By running `cargo new <name>` you will create a new rust project containing a git repository
Calling `cargo new --help` will bring up help view
the `Cargo.toml` file is always at the root of a rust project. Its essentially the `package.json` in npm
The dependency section contains whats called `Crates`. The central registry for all crates is found at [Crates.io](crates.io).
after a crate is installed, youll see the name of the crate, the version, and a thumb meaning its isntalled
```toml
[dependencies]
package = 1.0.0 👍
```
#### Building project
To build the cargo project you run `cargo build`. This will build all crates and your rust code.
#### Running project
To run the cargo project you run `cargo run` which will execute the binary file that was previously built
#### System wide crates
We can also use cargo to install rust binaries that can be used system wide. A tool called `cargo-expand` can be installed by running `cargo install cargo-expand` in the terminal
> this takes a minute
cargo-expand is using the nightly build of cargo/rust so you cannot call it in the terminal yet
lets check what we have installed by running `rustup toolchain list`. Looks like we're on the stable version
lets install the nightly toolchain using the following command
```bash
rustup toolchain install nightly-aarch64-apple-darwin
```
Now if we run `rustup toolchain list`, we'll see the nightly and the stable with stable being default - we can now call `cargo expand` in the terminal
---
### The stack
Rust calculates the size of a stack frame at compile time
This means, if a function contains a variable, the stack frame will have just enough space for that variable. If a new frame is added with a parameter and a variable, the stack frame will have just enough space for the two variable, slightly larger than the previous stack frame
The stack has a limited size, determined by the machine architecture, and will result in a stack overflow error if you overflow the stack with something like infinite recursion
---
### The Heap
##### What is the heap?
- its a region fo the process emmory that is NOT auto managed
- it has no size restrictions
- its accessible by any function, anywhere in the program
- we should avoid heap allocations as they are expensive
When you allocate a value on the heap, you store a pointer to the address of the allocated data
```rust
POINTER e = ALLOCATE INTEGER 7
// e = 0xf578bb60
```
memory is manually allocated and deallocate on the heap. If you dont deallocate the memory, you will have a memory leak, which wont be released until the program exits
---
### Smart Pointers
smart pointers essnetially just deallocate the heap memory automatically
```rust
let e = Box::new(7);
```
---
### Memory layout of binary
> who cares
---
### Basic data types
u8 - unsigned 8 bit (can only be positive)
i8 - signed 8 bit (can be negative)
u/i + size (8,16,32,128)
bool - 0/1
usize, isize - positive/negative size
char - single character (always 4 bytes)
---
### Functions
the `main()` function is the entry point to any rust application
function names are written in snake case i.e. `some_function_name()`
annotate all parameters
annotate return type
```rust
fn some_func(arg: f32) -> f32 {
// return f32 type
// if you dont use return keyword and without semicolon, value will be implicitly returned
}
```
We may see functions with a BANG attached to it, like so `someFunc!()`. That BANG indicates that this function is a MACRO.. A macro essentially is a shortcut to template code. So when we call the macro function, it will expand the code on build to something like so:
```rust
someFunc!('some arg');
// expands to
bunc::of::junk -> stuff -> no idea what im writing{
match(junk){
no idea -> 'some arg'
}
}
// this is just an example, this is nothing like the actual syntax of rust
```
---
### Variables
we use the `let` keyword to define variables
```rust
let newVar = 5;
```
There's no need to define variable types as the rust compiler can usually infer the type
All variables in rust are immutable by default. If we try to update the variable, the compiler will cry about it.
```rust
let a = 'b';
a = 'c' // compiler error: variable immutable
let mut a = 'b';
a = 'c';
// a == 'c'
```
---
### Standard Library
[STD](doc.rust-lang.org/std)
Module I/O (std::io)
```rust
// need to allocate empty mutable string first
let mut value = String::new(); // value lives on heap since size is not known at compile time - String is type of smart pointer
io::stdin().read_line(&mut value);
```
---
### Ownership
there are a few rules that variables follow:
1. each value in rust is owned by a variable
2. when the owner goes out of scope, the value will be deallocated
`let mut input = String::new()` where input is owner of String
3. there can only be ONE owner at a time
(`let mut input = String::new()` where input is owner of heap allocated String)
when passing owner to function, the function parameter now becomes the owner, and when that function is finished executing, you can no longer use the initial variable
```rust
let mut input = String::new(); // input is now owner
some_fn(input); // some_fn parameter is now owner
io::stdin().read_line(&mut input); // throws error as input is no longer available
```
> if you dont like this, see Borrowing
---
### Borrowing
by passing references, we can "borrow" a variable
```rust
fn some_fn(s: &string){} // s is not the owner of the string due to &
let val = String::new();
some_fn(&val) // reference is immutable
let mut val = String::new()
some_fn(&mut val) // reference is mutable
```
WITHIN a scope, you can have only one of:
1. as many immutable references as you want
2. one mutable reference
```rust
// cannot borrow 'input' as immutable because its already borrowed as mutable
```
---
### Result Type
When a method returns a type `Result`, it returns essentially a javascript promise with a success (then) and an error (catch).
you can call `.unwrap()` on the result
if result was a success, the unwrap will yield the contents of the success
if result was an error, it will terminate the application
---
### Parse string to number
Sometimes when getting input from the user for a number, you want to actually do some operation on that number.
```rust
io::stdin().read_line(&mut value).unwrap()
```
say we want to convert this `value` to an `f32` - you would first need to ensure the string is trimmed
```rust
let new_value = value.trim();
```
then you can call parse on the string
```rust
new_value.parse::<f32>().unwrap();
```
the `<f32>` part is so `parse` an ensure what type we're wanting to convert it into
---
### Resources
For more details on rust syntax, go to this file [[Rust Syntax overview]]
---
### End
Now lets head on over to creating a http server [[Rust http server]]