Updated: 2022-02-12 20:35:27+11:00

Please refer to Don Bright’s original rust-lang-cheat-sheet which I based much of this content off, as I work through the Rust in Motion course by Carol Nichols and Jake Goulding, rustlings and Rust in Action.

Rust in a nutshell

  • Syntax similar to C
  • Ownership of memory enforced at compile time
  • Statically linked
  • Functional-ish, generic-ish, not so objecty
  • Control flow using patterns, match keyword
  • Packages: ‘cargo’ command, https://crates.io
  • Testing: cargo test, #[test]
  • Concurrency: ownership, mutability, channels, mutex, crossbeam + Rayon packages
  • Auto formatter: rustfmt filename.rs
  • Compiler engine: LLVM
  • Raw pointers, low level: unsafe{} keyword



  • rustup doc for offline docs!
  • doc.rust-lang.org standard library, primitive types, standard macros
  • docs.rs for package documentation


$ rustup.sh               # install rust, see rust-lang.org for details
$ cargo new myproj        # start new executable project
$ cargo new --bin myproj  # as above
$ cargo new --lib myproj  # start new library project
$ cd myproj               # cd into the new directory
$ ls -lR                  # list our skeleton of files
src/main.rs               # main.rs, has main() entry point
Cargo.toml                # Cargo.toml defines packaging
$ $EDITOR Cargo.toml      # add dependencies and other details
name = "helloworld"
version = "0.1.0"
authors = ["Benjamin Simmonds <ben@bencode.net>"]

serde = "1.0.80"

$ cargo build             # downloads dependencies + builds main.rs
$ cargo build --release   # release build
$ cargo run               # runs program created from main.rs
$ cargo test              # runs tests (in parallel by default)
$ cargo test -- --test-threads=1  # run tests one at a time
$ cargo test -- --nocapture       # run tests, show output
$ cargo run --example fundemo -- --argtodemo # run example with argument


let x = false;           // all variable bindings are immutable by default
x = true;                // compile error: can't change an immutable binding
let mut p = false;       // "mut" designates a binding as mutable
p = true;                // ok, mutable binding can change;

Types and variables

let x: bool = false; // let keyword
let k = false;       // rustc can determine some types, this is idiomatic rust
let y: char = '上';  // all chars are 4 bytes
let  = 5;          // error. identifiers must be ASCII characters
let a: i8 = -2;      // 8 bit signed integers, also i16, i32, i64
let b: u8 = 200;     // 8 bit unsigned integers, also u16, u32, u64
let n: f32 = 0.45;   // 32 bit float (automatcally converted+rounded from decimal to binary)
let n = 42.01f64;  c // 64 bit float literal of the number 42.01 (approximately)
let r: [u8;3] = [3,4,5];          // array of 3 int, cannot grow
let s = [0;500];                  // array of 500 integers, each initialized to 0
let s = &r[0..2];                 // slice of array, s==&[3,4]
let s = &r[0..2][0];              // index into slice, s==3
let mut u:Vec<u8> = Vec::new();   // create empty vector of unsigned 8 bit int, can grow
let mut v = vec![3,4,5];          // initialize mutable vector using vec! macro
let w = vec![1,12,13];            // vectors can be immutable too
u.push( 2 );                      // append item to vector
u.pop();                      // vectors can return+remove last input (like a stack)
v.contains(&3);               // true if vector contains value
v.remove(1);                  // remove the nth item from a vector...
v.append(u);                  // append v with u (u becomes empty ([]), both mutable)
v.extend(w);                  // extend v with w (v owns w, w can be immutable)
v.resize(200,0);              // make vector have 200 elements, set them to 0
let x = &w[1..];              // get a slice of a vector (a view into it's elements)
print("{:?}",x);              // [12,13];
let vs = v.len();             // length of vector
let (p,d,q) = (4,5,6);        // tuple() can assign multiple variables at once
print("{}",p);                // you can use them alone after tuple assignment
let m = (4,5,"a");            // tuples can have multiple different types as elements
let (a,b) = m.0, m.2;         // tuple indexing with .0, .1, .2, etc
let (a,b) = m.p, m.q;         // error, cannot index into a tuple using a variable
let (x, y, z) = m;            // tuple destructuring into individual variables

let s = String::from("上善若水");  // String
let s2 = "水善利萬物而不爭";       // string literal, type is &str
let s3 = format!("{}{}",s2,s3);    // concatenate strings
for i in "말 한마디에 천냥 빚을 갚는다".split(" ") {print!("{}",i);} // split string
let s4 = s.get(0..2);              // Substring using indexes
let i4 = s.find('水').unwrap_or(-1); // find index of character (not a byte offset)
let hellomsg = r###"               // Multi-line with embedded quotes
 "Hello" in Chinese is 你好 ('Ni Hao')
 "Hello" in Hindi is नमस्ते ('Namaste')

usize, isize              // this is the pointer size. used in loops, vector length, etc

const BILBOG: i32 = 10;         // constant
static ORGOG: &str = "zormpf";  // static, global-ish variable
static FOOBY: i32 = 5;          // unsafely mutable
static Z_ERRMSG : [&str;2] = ["need input","need more input"]; // static strings

type Valid = bool;        // typedef ( make your own type names )

let mut v = vec![1u8,2u8,3u8];  // determine the type of expression expr by looking at rustc error
println!("{}",v.iter_mut());    // for example, if we want to know the type of v, build an error
12 |     println!("{}",v.iter_mut());   // type of v.iter_mut() is std::slice::IterMut<'_, u8>`
   |                   ^^^^^^^^^^^^ `std::slice::IterMut<'_, u8>` <- error line tells you the type

Unit tests, integration tests

Test functions are marked with the #[test] attribute.

Unit tests should be placed in the same file as the code being tested.


pub fn process(v:&mut Vec<u8>)->&Vec<u8>{ v.update(|x| f(x)) } // main function called by users
fn f(x:u8)->u8 { x*x }   // small piece of our code, to test in unit testing

#[cfg(test)]        // cfg -> section will only compiled during 'cargo test'
mod tests {         // namespace helper
    use super::*;   // bring in our functions above
    #[test]         // next function will be a single test
    fn test_f() { assert!(f(4)==16); } // test f() by itself (unit)

Integration tests, for overall crate, lives under ./tests/*.rs

./tests/file.rs:         // will only be built dring 'cargo test'
extern crate mypackage;  // include package we are testing
#test                    // treat next function as a test
fn bigtest() {           // not a unit test. instead, test overall code
	let mut d = vec![1,2,3];               // set up some typical data users would have
	let expected_results = vec![1,4,9];    // some results we expect
	assert!(process(d)==expected_results); // test what a user would typically call, process()
$ cargo test           # test build, will include cfg(test) sections
-> test_f passed       # cargo reports on passed tests
-> test_bigtest failed # cargo reports on failed tests


rust-doc and cargo doc allow automatic building of html documentation for code. precede documentation of your code with three slashmarks instead of the normal two slashmarks, like so:

/// blorg() returns the blorgification of input x
/// # Details
/// this code implements the krishnamurthi procedure
/// for blimfication of zorgonautic primes
/// # Arguments
/// * `x` - typically a square number
/// # Safety
/// Cannot panic unless x overflows u64
/// # Example
///     let n = blorg(36);
fn blorg(x:u64)->u64 {

Then run rust-doc or cargo doc and view the result.

$ cargo doc
$ firefox target/doc/cratename/index.html

Good examples of the results are on https://crates.io


Jon Gjengset is my hero. Not only is Jon a genius, he’s an absolute machine doing 5+ hour live coding streams tackling difficult and low-level problems using Rust, such as building your own TCP/IP stack from the ground up. Checkout his site, YouTube channel and Tweets for upcoming live stream which are not to be missed.