# Rust Note {%hackmd @RintarouTW/About %} [The Rust Programming Language](https://doc.rust-lang.org/book/) [Command line apps in Rust](https://rust-cli.github.io/book/index.html) [Rust and WebAssembly](https://rustwasm.github.io/docs/book/introduction.html) [The Unstable Book](https://doc.rust-lang.org/nightly/unstable-book/the-unstable-book.html) [The Rust Reference](https://doc.rust-lang.org/reference/introduction.html) [The Rust Sandard Library](https://doc.rust-lang.org/std/index.html) ## Environment rustc - compiler cargo - package manager ```!bash cargo new project cargo build --release // optimized cargo build // for dev, nonoptimized, including symbols cargo run ``` ## Package Repository https://crates.io/ update packages ```!bash cargo update ``` ## Packages, Crates, Modules and Workspaces - Packages: A Cargo feature that lets you build, test and share crates. - Creates: A tree of modules that produces a library or executale. - Modules and use: Let you control the organization, scope and privacy of paths. - Paths: A way of naming an item, such as a struct, function, or module. ### Package A package is one or more crates that provide a set of functionality. A package contains a **Cargo.toml** file that describes how to build those crates. - src/main.rs : the crate root of a binary crate with the same name as the package. - src/lib.rs : the package contains a library crate with the same name as the pacakge. it's the crate root of a library. if a package contains both src/main.rs and src/lib.rs, then it has two crates: a library and a binary. ### Modules paths that allow you to name items; - the **use** keyword that brings a path into scope; - the **pub** keyword to make items as public - the **as** keyword ... Modules let us organize code within a crate into groups for reability and easy reuse. ``` cargo new --lib library_name ``` Example: **src/lib.rs** ```!rust mod front_of_house { mod hosting { fn add_to_waitlist() {} fn ... } mod serving { fn ... } } ``` define a module with **mod** keyword. the entire module tree is rooted under the implicit module named **crate**. ### Path Paths for referring to an item in the module tree. - absolute path: starts from a crate root by using a crate name or literal crate. - relative path: starts from the current module and use **self**, **super**, or an identifier in the current module. Ex: ```!rust pub fn test() { // absolute path crate::front_of_house::hosting::add_to_waitlist(); // relative path front_of_house::hosting::add_to_waitlist(); } ``` **Starting Relative Paths with super** ```!rust fn serve_order() {} mod back_of_house { fn fix_incorrect_order() { cook_order(); super::serve_order(); } fn cook_order() {} } fn main() {} ``` ## Languages **Variables are immutable by defaul** ```!rust let a = 1; // immutable let mut b = 2; // mutable const C = 3; // constant and should be in upper cases. ``` **Loop** ```!rust loop { break; continue; } ``` **traits** build documentation of packages ```!bash cargo doc --open ``` **Shadowing** redefine is allowed in Rust, called **Shadowing**. ```!rust let a = "abc"; let a : u32 = 123; ``` ```!rust let x = 5; let x = x + 1; let x = x * 2; println!("The value of x is: {}", x); x = 12 ``` shadowing is actually creating another veriable internally by the rustc. it's not the same with **mut**. ### Data Types **Scalar Types** ``` i8, u8 i16, u16 i32, u32 i64, u64 i128, u128 isize, usize // by arch f32, f64 ``` **Number Operations** $$ \cases{ +\\ -\\ *\\ /\\ \%\\ } $$ **Character Type** single quote, unicode support ```!rust let c = 'z'; ``` **Tuple** ```!rust let tup : (i32, u64, f32) = (1, 2, 3.0); let (x, y, z) = tup; ``` **expression vs statement** expression without ; as return value, and statement required ; **functions** ```!rust fn func(x: type) -> return_type { ... return value with expression } ``` **control flow** - if with no () - loop {} - for {} - while {} **Result<T, E>** ```!rust enum Result<T, E>{ Ok(T), Err(E), } ``` **Option<T>** ```!rust enum Option{ Some(Val), None, } ``` ## Ownership Rules - Each value in Rust has a variable that's called it's owner. - There can only be one owner at a time. - When the owner goes out of scope, the value will be dropped. :::warning value's owner would be moved to function(), unless using & reference instead. ::: call by reference was called **borrowing** in Rust. Reference is like variable as immutable by default. **Mutable Reference** :::warning mutable reference can only be borrowed once at a time. ::: this ristriction is to prevent data races at compile time. ## Memory Much more strict than other languages. - Return memory once it's not used in code level. not even the end of the function. - Ownership would change to another function by simply (call by value in C++). ### Collections - Vec - String - HashMap ## Error Handling ```!rust enum Result<T, E> { Ok(T), Err(E), } ``` ## Trait like interface. but, - default implementation is allowed. - imp XXX for struct/enum - strict to local implementation. no overwrite to other's implementation. ## Smart Pointer in Rust - Deref Trait : Make an instance of smart pointer behave like a reference. - Drop Trait : Allow you to customize ur code to run when an instance of smart pointer is out of scope. Common smart pointers in std, - Box<T> for allocating values on the heap - Rc<T>, a reference counting type that enables multiple ownership - Ref<T> and RefMut<T>, accessed through RefCell<T>, a type that enforces the borrowing rules at runtime instead of compile time ## Unsafe Rust ## Todo ### how enum() hold the value in memory? ### read vec![] docs to clearify ```!rust let vecs = vec![...]; for v in vecs { } for v in vecs.iter() { } ``` ### take() take the value from the Box<T> ### unwrap()? ### object-safe?? from what?? need definition. ### what's the difference between String and str? **String** is a smart pointer implementation of String. **str** is "String Slice" a &str is two values: the address(as_ptr) of the str and its length(len), we can know the size of a &str value at compile time: it’s twice the length of a usize. &T is a reference(pointer) to the T typed data structure. ### is there a way to show &ref value(raw pointer)? Dereference a raw pointer in unsafe Rust. ```!rust fn main() { let mut num = 5; let r1 = &num as *const i32; let r2 = &mut num as *mut i32; } ``` ### match only match one arm ### module files src/lib.rs ```!rust mod front_of_house; pub use crate::front_of_house::hosting; pub fn eat_at_restaurant() { hosting::add_to_waitlist(); hosting::add_to_waitlist(); hosting::add_to_waitlist(); } ``` src/front_of_house.rs ```!rust ... implmentations of front_of_house module ``` ### Multi-threads and channels ```!rust let (tx, rx) = mpsc:: ... // blocking tx.send(val) rs.recv() // nonblocking tx.send_... rx.recv_... ``` ### Study more about Rust Macros. [Macros By Example](https://doc.rust-lang.org/reference/macros-by-example.html) [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html) - ast (syntax tree) - macro_rules! - procedural macro - attribute macro ## Terms **unit-like** () is actually a tuple without numbers. **tuple struct** struct Foo(); **fn** fn is actually a function pointer. ## Core Traits ### Trait core::convert::From https://doc.rust-lang.org/nightly/core/convert/trait.From.html value-to-value conversions Implementing **From** automatically provides one with an implementation of **Into**. - From<T> for U implies \<U> for T - From is reflexive, so From<T> for T is implemented. ex: ```!rust use std::fs; use std::io; use std::num; enum CliError { IoError(io::Error), ParseError(num::ParseIntError), } impl From<io::Error> for CliError { fn from(error: io::Error) -> Self { CliError::IoError(error) } } impl From<num::ParseIntError> for CliError { fn from(error: num::ParseIntError) -> Self { CliError::ParseError(error) } } fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> { let mut contents = fs::read_to_string(&file_name)?; let num: i32 = contents.trim().parse()?; Ok(num) } ``` ###### tags: `rust`