Rust Note

學海無涯,思境無維;數乃六藝,理之始也。
或有一得足矣 愚千慮

The Rust Programming Language

Command line apps in Rust

Rust and WebAssembly

The Unstable Book

The Rust Reference

The Rust Sandard Library

Environment

rustc - compiler
cargo - package manager

cargo new project
cargo build --release // optimized 
cargo build   // for dev, nonoptimized, including symbols
cargo run

Package Repository

https://crates.io/

update packages

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

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:

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() {}

Languages

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.

Data Types

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

  • if with no ()
  • loop {}
  • for {}
  • while {}

Result<T, E>

enum Result<T, E>{
    Ok(T),
    Err(E),
}

Option<T>

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.

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.

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

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

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.

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

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

Multi-threads and channels

let (tx, rx) = mpsc:: ...

// blocking
tx.send(val)
rs.recv()

// nonblocking
tx.send_...
rx.recv_...

Study more about Rust Macros.

Macros By Example

The Little Book of Rust Macros

  • 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:

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