rustc - compiler
cargo - package manager
cargo new project
cargo build --release // optimized
cargo build // for dev, nonoptimized, including symbols
cargo run
update packages
cargo update
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.
if a package contains both src/main.rs and src/lib.rs, then it has two crates: a library and a binary.
paths that allow you to name items;
Modules let us organize code within a crate into groups for reability and easy reuse.
cargo new --lib library_name
Example:
src/lib.rs
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.
Paths for referring to an item in the module tree.
Ex:
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
fn serve_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::serve_order();
}
fn cook_order() {}
}
fn main() {}
Variables are immutable by defaul
let a = 1; // immutable
let mut b = 2; // mutable
const C = 3; // constant and should be in upper cases.
Loop
loop {
break;
continue;
}
traits
build documentation of packages
cargo doc --open
Shadowing
redefine is allowed in Rust, called Shadowing.
let a = "abc";
let a : u32 = 123;
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.
Scalar Types
i8, u8
i16, u16
i32, u32
i64, u64
i128, u128
isize, usize // by arch
f32, f64
Number Operations
Character Type
single quote, unicode support
let c = 'z';
Tuple
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
fn func(x: type) -> return_type {
...
return value with expression
}
control flow
Result<T, E>
enum Result<T, E>{
Ok(T),
Err(E),
}
Option<T>
enum Option{
Some(Val),
None,
}
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
mutable reference can only be borrowed once at a time.
this ristriction is to prevent data races at compile time.
Much more strict than other languages.
enum Result<T, E> {
Ok(T),
Err(E),
}
like interface. but,
Common smart pointers in std,
let vecs = vec![...];
for v in vecs {
}
for v in vecs.iter() {
}
take the value from the Box<T>
need definition.
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.
Dereference a raw pointer in unsafe Rust.
fn main() {
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
}
src/lib.rs
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
... implmentations of front_of_house module
let (tx, rx) = mpsc:: ...
// blocking
tx.send(val)
rs.recv()
// nonblocking
tx.send_...
rx.recv_...
The Little Book of Rust Macros
unit-like
() is actually a tuple without numbers.
tuple struct
struct Foo();
fn
fn is actually a function pointer.
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.
ex:
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)
}
rust