Rust Cheat Sheet

Variables (let, mut, const)

let x = 5;          // immutable
let mut y = 10;     // mutable
const MAX: u32 = 100_000; // constant

Data Types (i32, f64, bool, char, &str, String)

let a: i32 = -5;
let b: f64 = 3.14;
let c: bool = true;
let d: char = 'R';
let e: &str = "hello";
let f: String = String::from("world");

Type Inference

Rust can infer types based on usage.

let score = 42;        // i32
let pi = 3.1415;       // f64

Comments

// This is a single-line comment
/* This is a 
   multi-line comment */

Printing (println!, dbg!)

println!("Hello, {}!", name);
dbg!(x + y);

if / else / match

if x > 0 {
  println!("Positive");
} else {
  println!("Non-positive");
}

match x {
  1 => println!("One"),
  2..=5 => println!("Few"),
  _ => println!("Other"),
}

Loops (loop, while, for)

loop {
  break;
}

while x < 10 {
  x += 1;
}

for i in 0..5 {
  println!("{}", i);
}

break / continue

for i in 1..10 {
  if i % 2 == 0 {
    continue;
  }
  if i > 5 {
    break;
  }
  println!("{}", i);
}

Function Declaration

fn add(x: i32, y: i32) -> i32 {
  x + y
}

Closures

let add = |a, b| a + b;
println!("{}", add(2, 3));

Function Pointers (fn)

fn multiply(x: i32, y: i32) -> i32 {
  x * y
}
let func: fn(i32, i32) -> i32 = multiply;

Ownership Rules

Each value in Rust has a single owner. When the owner goes out of scope, the value is dropped.

let s1 = String::from("hello");
let s2 = s1; // ownership moves, s1 is no longer valid

References (&, &mut)

fn print(s: &String) {
  println!("{}", s);
}

fn modify(s: &mut String) {
  s.push_str(" world");
}

Borrow Checker

Ensures safe memory access rules: either one mutable reference or multiple immutable references at a time.

let r1 = &s;
let r2 = &s; // OK
let r3 = &mut s; // ERROR: can't borrow mutably while borrowed immutably

Lifetimes

Explicit lifetime annotations ensure references are valid as long as needed.

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
  if x.len() > y.len() { x } else { y }
}

Tuples

let tup = (1, "hello", 4.5);
let (a, b, c) = tup;
println!("{} {} {}", a, b, c);

Arrays & Slices

let arr = [1, 2, 3, 4];
let slice = &arr[1..3];

Vectors (Vec<T>)

let mut v = Vec::new();
v.push(1);
v.push(2);

Strings (&str, String)

let s1 = "literal";           // &str
let s2 = String::from("heap"); // String

HashMap & HashSet

use std::collections::{HashMap, HashSet};

let mut map = HashMap::new();
map.insert("a", 1);

let mut set = HashSet::new();
set.insert("a");

Enums & Pattern Matching

enum Direction {
  North,
  East,
  South,
  West,
}

let dir = Direction::North;
match dir {
  Direction::North => println!("Up"),
  _ => println!("Other"),
}

Structs (Regular, Tuple, Unit)

struct Point { x: i32, y: i32 }
struct Color(i32, i32, i32);
struct Marker;

Error Handling

let result: Result = Ok(10);
match result {
  Ok(val) => println!("Value: {}", val),
  Err(e) => println!("Error: {}", e),
}

let option: Option = Some(5);
if let Some(x) = option {
  println!("Found: {}", x);
}

let x = result.unwrap();
let y = result.expect("Expected a number");

Modules & Packages

mod greetings {
  pub fn hello() {
    println!("Hello");
  }
}

use greetings::hello;

// Cargo commands
// cargo new my_project
// cargo build, run, test

Traits & Generics

trait Greet {
  fn greet(&self);
}

struct Person;
impl Greet for Person {
  fn greet(&self) {
    println!("Hi");
  }
}

fn print_val(val: T) {
  println!("{:?}", val);
}

Memory & Safety

// Stack: fixed size, fast access
// Heap: dynamic size, manual management

use std::rc::Rc;
use std::cell::RefCell;

let b = Box::new(5);
let r = Rc::new(RefCell::new(10));

Concurrency

use std::thread;
use std::sync::{Arc, Mutex};

let handle = thread::spawn(|| {
  println!("Hello from thread");
});
handle.join().unwrap();

let data = Arc::new(Mutex::new(0));

Macros

println!("Hello, {}", name);
vec![1, 2, 3];
format!("{}", 123);

macro_rules! say_hello {
  () => {
    println!("Hello!");
  };
}

Useful std Lib Features

// Iterators
let v = vec![1, 2, 3];
let sum: i32 = v.iter().map(|x| x * 2).sum();

// File I/O
use std::fs::File;
use std::io::prelude::*;
let mut file = File::create("foo.txt")?;
file.write_all(b"Hello")?;

// Command Line Args
use std::env;
for arg in env::args() {
  println!("{}", arg);
}

// Time
use std::time::{Instant, Duration};
let now = Instant::now();

Misc

Pattern Matching

let (x, y) = (1, 2);
match (x, y) {
  (0, _) => println!("x is zero"),
  (_, 0) => println!("y is zero"),
  _ => println!("Neither is zero"),
}

Shadowing

let x = 5;
let x = x + 1;

Type Casting (as)

let x = 5;
let y = x as f64;

Const & Static

const MAX_POINTS: u32 = 100_000;
static GREETING: &str = "Hello";

Unit Type ()

fn do_nothing() { }
let unit: () = do_nothing();