Rust Cheatsheet

kuniga.me > Docs > Rust Cheatsheet

Rust Cheatsheet

Index

  1. Basic types
    1. Type names
    2. Arrays
      1. Initialize
      2. Iterate
    3. Bool
    4. Enum
    5. Integers
      1. Bit operations
    6. Iterator
    7. Optional
    8. Pair
    9. String
      1. Types
      2. String (variable length)
      3. Operations
    10. Struct
      1. Destructuring
      2. Methods
    11. Tuple
  2. Functions
    1. Closure
      1. Multi-line
  3. Flow Control
    1. Conditional
    2. Loops
  4. Data structures
    1. Vector
      1. Initialize
      2. Inserting
      3. Iterating
      4. Mapping
      5. Filtering
      6. Length
      7. Sorting
      8. Destructured assignment
    2. HashMap
    3. Set
    4. Queue
  5. Object Oriented
  6. I/O
    1. Read from stdin
    2. Read CLI arguments
    3. Printing to stdout
  7. Math
    1. Exponentiation
    2. Square root
  8. Mutability

Basic types

Type names

Arrays

Arrays are of fixed size. For variable size, see Vec.

Initialize

// Initialize array
let arr: [i32; 3] = [1, 2, 3];
let arr: [i32; 10] = [0; 10];

Iterate

let it:
let v: Option<Self::Item> = it.next()

Bool

Enum

enum Direction {
    N,
    E,
    S,
    W,
}

Integers

Bit operations

! is the Rust version of ~

Iterator

Note that Iterator is not a class but rather a trait that classes implement.

Get the next element:

// returns Split class which implements Iterator
let mut parts = s.split(',');
let e: Optional<&str> = parts.next();

NOTE: next() is not idempotent.

Optional

// Handle option:
match my_option {
    Some(value) => value,
    None => 1, // handle null value
}

Create Some:

Some(1)

Throw if None:

my_option.unwrap()

Test if some:

my_option.is_some()

Test if none:

my_option.is_none()

Pair

Done via tuples. See Tuple.

String

Types

String (variable length)

// Empty string
let mut my_str: String = "".to_owned();

// Other form
let mut my_str = String::from("Hello");

// Length
my_str.len();

// Iterate over its characters
for c in my_str.chars() {
    // do something with c
}

Operations

let concatenated = format!("{}{}", a, b);

From literal strings:

let s: String = "hello".to_owned();

Convert to int:

let i = s.parse::<i32>().expect("Should be numeric");

Convert from int:

let i: i32 = 10;
let s = i.to_string();

Convert to Vec<char>:

let cs: Vec<char> = s.chars().collect();

Split:

let parts: Vec<&str> = s.split(',').collect();

Split into multiple lines. There’s a shortcut for splitting by the character \n:

let parts: Vec<&str> = s.lines().collect();

Substring:

s.contains(p);

Trim:

let trimmed = s.trim();

Struct

keywords: record / object / shape

struct Tree {
    guess: Vec<i32>,
    children: Vec<Tree>,
}

Destructuring

let foo = Foo { x: (1, 2), y: 3 };
let Foo { x: (a, b), y } = foo;

Methods

struct Rectangle {
    length: u32,
    width: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.length * self.width
    }
}

Tuple

Type: (T1, T2), e.g. (i32, bool)

Create:

let tup: (i32, String) = (64, "hello")

Access:

tup.0 // 64
tup.1 // "hello"

or via destructuring:

let (n, s) = &tup;

Functions

fn myFun(arg1: i32, arg2: i32) -> i32 {
}

Rust doesn’t support default arguments

Closure

keywords: lambda

    let plus_one = |x: i32| x + 1;

Multi-line

let multi_line = |x: i32| {
    let mut result: i32 = x;
    result += 1;
    result
}

Flow Control

Conditional

if n < 0 {
    print!("{} is negative", n);
} else if n > 0 {
    print!("{} is positive", n);
} else {
    print!("{} is zero", n);
}

Loops

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

See also “Iterating” on different data structures.

Data structures

Vector

Initialize

let mut vec = Vec::new();

Fixed size, same value:

let mut vec = vec![0; 100];

Inserting

vec.push(1);

Iterating

for item in vec.iter() {
    ...
}

Mapping

let u = vec![1, 2, 3];
let v: Vec<_> = u.iter().map(f).collect();

Filtering

let u = vec![1, 2, 3];
let v: Vec<_> = u.iter().filter(f).collect();

In-place

let mut u = vec![1, 2, 3];
u.retain(f);

Length

vec.len()

Sorting

vec.sort_by(|a, b| a.cmp(b))

Destructured assignment

Like in Python, we can do destructured assignment by assuming a fixed length of a vector, but we have to handle the other cases:

let [a, b] = vec.as_slice() else {
    panic!();
}

HashMap

Reference: HashMap

use std::collections::HashMap;

// Type definition
HashMap<String, String>;

// Create New
let mut my_map = HashMap::new()

// Create New Initialized
let my_map = HashMap::from([
    ("blue", 1),
    ("green", 2),
    ("red", 3),
]);

// Insert
my_map.insert(
    "key_a".to_string(),
    "value_a".to_string(),
);

// Access
match my_map.get("key_a") {
    Some(value) => println!("value={}", value),
    None => println!("not found")
}

// Update
if let Some(value) = my_map.get_mut(key) {
    *curr_value = 1;
}

// All values
for value in my_map.values() {
}

// All keys
for key in my_map.keys() {
}

Set

Use:

use std::collections::HashSet;

Create:

let s = HashSet::new();

From vector:

let v = vec![1, 2, 3];
// cloned needed if borrowing v
let s: HashSet<_> = v.iter().cloned().collect();

Set intersection:

let i: HashSet<_> = s1.intersection(&s2).cloned().collect();

Queue

use std::collections::VecDeque;

// Create
let mut queue = VecDeque::new();

// Enqueue
queue.push_back("a");

// Dequeue
if let Some(x) = queue.pop_front() {
    // use x
}

// Is empty?
if !queue.is_empty() {
    // use queue
}

Object Oriented

pub structure MyClass {
    my_field: bool,
}

impl MyClass {
    // Constructor-like
    pub fn new() -> MyClass {
        return MyClass {
        my_field: true,
        }
    }

    // Read Method
    pub fn set(&self, value: bool) {
        self.my_field = value;
    }

    // Write Method
    pub fn set(&mut self, value: bool) {
        self.my_field = value;
    }
}

I/O

Read from stdin

use std::io::{self, Read};

let mut input = String::new();
io::stdin().read_to_string(&mut input)
    .expect("Failed to read input");

Read CLI arguments

use std::env;

// Skip program name
let args: Vec<String> = env::args().skip(1).collect();

Printing to stdout

Vector:

let vec = vec![1, 2, 3, 4, 5];
println!("Vector:\n{:#?}", vec);

Math

A lot of the math operations are methods on the numerical types.

Exponentiation

let b: i32 = 10;
let p10: i32 = b.pow(2 as u32);

Note that the exponent has to be positive, since a negative one could change the type of the base to floating point.

Square root

let x: f64 = 10.0;
let y: f64 = x.sqrt();

Not defined for integer types.

Mutability

Variable doesn’t need to be mutable if it’s initialized only once:

let x: i32;

if check() {
    x = 1;
} else {
    x = 2;
}