Rust Cheatsheet

Data Types

Use this Rust reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Integer Types

TypeSizeRange
i88-bit−128 to 127
i1616-bit−32,768 to 32,767
i3232-bit−2.1B to 2.1B (default)
i6464-bit±9.2×10¹⁸
i128128-bit±1.7×10³⁸
isizepointer-sizedplatform-dependent
u8..u128, usizesame sizes0 to 2ⁿ−1
let a: i32 = -42;
let b = 255u8;
let c = 1_000_000i64;    // underscores for readability
let hex = 0xFF;           // 255
let octal = 0o17;         // 15
let binary = 0b1111_0000; // 240
let byte = b'A';          // u8 value 65

// Checked arithmetic (no panic on overflow in release)
let checked = 200i32.checked_add(100);  // Some(300)
let overflow = 127i8.checked_add(1);    // None

// Wrapping / saturating / overflowing
let w = 127i8.wrapping_add(1);    // -128
let s = 200u8.saturating_add(100); // 255
let (o, overflowed) = 200u8.overflowing_add(100); // (44, true)

Floating-Point Types

let x: f64 = 3.14;   // default float type
let y: f32 = 2.718;

// Special values
let inf = f64::INFINITY;
let neg_inf = f64::NEG_INFINITY;
let nan = f64::NAN;

f64::is_nan(nan);       // true
f64::is_infinite(inf);  // true
f64::is_finite(3.14);   // true

// Constants
f64::MAX          // 1.7976931348623157e308
f64::MIN_POSITIVE // 2.2250738585072014e-308
f64::EPSILON      // 2.220446049250313e-16

// Math methods
let n: f64 = 2.0;
n.sqrt()       // 1.4142...
n.cbrt()       // cube root
n.abs()        // absolute value
n.ceil()       // 2.0
n.floor()      // 2.0
n.round()      // nearest integer
n.trunc()      // truncate decimal
n.fract()      // fractional part: 0.0
n.powi(3)      // integer exponent: 8.0
n.powf(0.5)    // float exponent: 1.414...
n.exp()        // eⁿ
n.exp2()       // 2ⁿ
n.ln()         // natural log
n.log2()       // log base 2
n.log10()      // log base 10
n.log(3.0)     // log base 3
n.sin()  n.cos()  n.tan()
n.asin() n.acos() n.atan()
n.atan2(1.0)   // two-arg arctangent
n.sinh() n.cosh() n.tanh()
n.hypot(1.0)   // √(n² + 1²)
n.min(3.0)  n.max(1.0)
n.clamp(0.0, 1.0)

Boolean

let t: bool = true;
let f: bool = false;

// Boolean operations
!t          // false
t && f      // false (short-circuits)
t || f      // true  (short-circuits)
t & f       // false (no short-circuit)
t | f       // true  (no short-circuit)
t ^ f       // true  (XOR)

// Convert to int
true as i32   // 1
false as i32  // 0

Characters

char is a Unicode scalar value — 4 bytes (not a byte!).

let c = 'z';
let emoji: char = '🦀';
let escaped = '\n';   // newline
let unicode = '\u{1F600}'; // 😀

// Methods
'a'.is_alphabetic()    // true
'5'.is_numeric()       // true (Unicode numeric)
'5'.is_ascii_digit()   // true
' '.is_whitespace()    // true
'A'.is_uppercase()     // true
'a'.is_lowercase()     // true
'a'.to_uppercase().next() // Some('A')
'A'.to_lowercase().next() // Some('a')
'a' as u32             // 97 (Unicode code point)
char::from(65u8)       // 'A'

Tuples

Fixed-size, heterogeneous, ordered collection. Index with .0, .1, etc.

let tup: (i32, f64, bool) = (500, 6.4, true);

// Destructure
let (x, y, z) = tup;
println!("{} {} {}", x, y, z);

// Field access
let five_hundred = tup.0;
let six_point_four = tup.1;

// Unit tuple (empty)
let unit: () = ();

// Single-element tuple (note the comma)
let single = (42,);

Arrays

Fixed-size, same type, stack-allocated.

let arr: [i32; 5] = [1, 2, 3, 4, 5];
let zeros = [0; 10];  // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

// Access (panics on out-of-bounds)
let first = arr[0];
let last = arr[4];

// Slice of array
let slice: &[i32] = &arr[1..3];  // [2, 3]

// Length
arr.len()     // 5

// Iteration
for x in &arr { println!("{}", x); }
for (i, x) in arr.iter().enumerate() { println!("{}: {}", i, x); }

Strings: str vs String

Feature&strString
AllocationStack / staticHeap
MutabilityImmutableMutable
OwnershipBorrowedOwned
Common useString literals, function paramsOwned, growable strings
// &str — string slice
let s: &str = "hello";
let owned = s.to_owned();        // &str → String
let owned2 = String::from("hi"); // &str → String
let borrowed: &str = &owned;     // String → &str (deref coercion)

// String creation
let mut s = String::new();
let s = "initial".to_string();
let s = format!("{} {}", "hello", "world");

// Appending
let mut s = String::from("hello");
s.push(' ');           // push char
s.push_str("world");   // push &str
s += " again";         // moves s, appends (uses Add trait)
let s3 = s1 + &s2;     // s1 moved; s2 borrowed

// String methods
s.len()                  // byte length
s.is_empty()
s.contains("world")
s.starts_with("hel")
s.ends_with("ld")
s.find("wor")            // Option<usize> byte index
s.rfind("l")             // last occurrence
s.replace("l", "r")      // new String
s.replacen("l", "r", 1)  // replace first n
s.to_uppercase()
s.to_lowercase()
s.trim()                  // strip leading+trailing whitespace
s.trim_start()
s.trim_end()
s.trim_matches('x')       // trim specific char/pattern
s.split(' ')              // iterator of &str
s.split_whitespace()
s.splitn(2, ':')          // split into at most n parts
s.lines()                 // iterate lines
s.chars()                 // iterate Unicode chars
s.bytes()                 // iterate bytes (u8)
s.char_indices()          // (byte_index, char) iterator
s.parse::<i32>()          // parse to type: Result<i32, _>
s.repeat(3)               // "abcabcabc"

// Slicing (byte indices, must be char boundaries!)
let hello = &s[0..5];

// Check and get chars safely
s.chars().nth(0)          // Option<char>
s.chars().count()         // number of Unicode chars

// String capacity
let mut s = String::with_capacity(50);
s.capacity()
s.reserve(10)

Vectors (Vec<T>)

Growable, heap-allocated array.

// Creation
let v: Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
let v = Vec::with_capacity(10);

// Mutation
let mut v = Vec::new();
v.push(1);
v.push(2);
v.pop();             // Option<T>
v.insert(0, 99);     // insert at index
v.remove(0);         // remove at index, returns element
v.clear();
v.extend([4, 5, 6]); // append from iter
v.append(&mut other_vec);  // drains other_vec

// Access
v[0]              // panics if out of bounds
v.get(0)          // Option<&T>, safe
v.first()         // Option<&T>
v.last()          // Option<&T>

// Info
v.len()
v.is_empty()
v.capacity()

// Sorting
v.sort();
v.sort_by(|a, b| a.cmp(b));
v.sort_by_key(|x| x.abs());
v.sort_unstable();    // faster, not stable

// Search
v.contains(&3)
v.binary_search(&3)       // Result<usize, usize> (must be sorted)
v.iter().position(|&x| x == 3)  // Option<usize>
v.iter().find(|&&x| x > 2)      // Option<&T>

// Slice ops
v.reverse()
v.dedup()           // remove consecutive duplicates
v.retain(|&x| x > 0)  // keep only matching
v.truncate(3)       // shorten to length 3
v.drain(1..3)       // remove range, returns iterator
v.split_at(2)       // (&[T], &[T])
v.windows(3)        // overlapping windows
v.chunks(2)         // non-overlapping chunks

HashMap

use std::collections::HashMap;

let mut scores: HashMap<String, i32> = HashMap::new();

// Insert
scores.insert(String::from("Alice"), 100);
scores.insert(String::from("Bob"), 85);

// Entry API (insert-or-update)
scores.entry(String::from("Alice")).or_insert(0);     // don't overwrite
scores.entry(String::from("Carol")).or_insert(50);    // inserts 50
*scores.entry("Bob".to_string()).or_insert(0) += 10;  // update

// Access
scores.get("Alice")          // Option<&i32>
scores["Alice"]              // panics if missing
scores.contains_key("Alice") // bool
scores.len()
scores.is_empty()

// Remove
scores.remove("Bob");        // Option<i32>

// Iteration
for (key, value) in &scores { println!("{}: {}", key, value); }
scores.keys()
scores.values()
scores.values_mut()
scores.iter()
scores.iter_mut()

// Build from iterator
let map: HashMap<&str, i32> = [("a", 1), ("b", 2)].into_iter().collect();

HashSet

use std::collections::HashSet;

let mut set: HashSet<i32> = HashSet::new();
set.insert(1);
set.insert(2);
set.insert(1);    // duplicate ignored

set.contains(&1)  // true
set.remove(&1)
set.len()

// Set operations
let a: HashSet<i32> = [1, 2, 3].into_iter().collect();
let b: HashSet<i32> = [2, 3, 4].into_iter().collect();

a.union(&b).collect::<HashSet<_>>()         // {1,2,3,4}
a.intersection(&b).collect::<HashSet<_>>()  // {2,3}
a.difference(&b).collect::<HashSet<_>>()    // {1}
a.symmetric_difference(&b)                   // {1,4}
a.is_subset(&b)
a.is_superset(&b)
a.is_disjoint(&b)

Range Types

let r = 1..5;    // Range<i32>: 1, 2, 3, 4 (exclusive end)
let r = 1..=5;   // RangeInclusive<i32>: 1, 2, 3, 4, 5
let r = 1..;     // RangeFrom: 1, 2, 3, ...
let r = ..5;     // RangeTo: ..5 (in slices only)
let r = ..=5;    // RangeToInclusive
let r = ..;      // RangeFull: full range (in slices)

for i in 0..10 { /* 0 to 9 */ }
(0..5).contains(&3)    // true
(0..5).rev()           // 4, 3, 2, 1, 0
(0..10).step_by(2)     // 0, 2, 4, 6, 8

Type Aliases

type Meters = f64;
type Thunk = Box<dyn Fn() -> ()>;
type Result<T> = std::result::Result<T, std::io::Error>;

let distance: Meters = 5.0;

The Option<T> Type

let some: Option<i32> = Some(42);
let none: Option<i32> = None;

// Unwrapping
some.unwrap()               // panics if None
some.unwrap_or(0)           // default if None
some.unwrap_or_else(|| 0)   // lazy default
some.unwrap_or_default()    // T::default() if None
some.expect("msg")          // panics with message if None

// Checking
some.is_some()
some.is_none()

// Transform
some.map(|x| x * 2)         // Option<i32>
some.map_or(0, |x| x * 2)   // i32
some.and_then(|x| Some(x + 1))  // flatMap
some.or(Some(99))            // self or other if None
some.or_else(|| Some(99))
some.filter(|&x| x > 0)     // None if predicate false
some.flatten()               // Option<Option<T>> → Option<T>

// Convert
some.ok_or("error")          // Option → Result
some.as_ref()                // Option<&T>
some.as_mut()                // Option<&mut T>
some.take()                  // takes value, leaves None
some.replace(99)             // replaces value, returns old

// Pattern match
if let Some(x) = some { println!("{}", x); }
let x = some?;               // return None from fn if None (? operator)