ENGIMY.IO - CHEATSHEET
RUST × QUICK REFERENCE
REFERENCE vRust 1.80

Rust Quick Reference

Everything you need day‑to‑day – syntax, ownership, and modern features.

Basic Syntax

fn main() {
    println!("Hello, World!");
}

Variables & Mutability

// Immutable by default
let x = 5;
x = 6;  // error

// Mutable
let mut y = 5;
y = 6;  // ok

// Constants
const PI: f64 = 3.14159;
const STATUS_OK: u32 = 200;

// Shadowing
let x = 5;
let x = x + 1;  // new variable shadows old one

// Type annotation
let age: i32 = 25;
let name: &str = "Alice";

Data Types

Scalar Types
  • i8, i16, i32, i64, i128signed
  • u8, u16, u32, u64, u128unsigned
  • f32, f64floating point
  • booltrue / false
  • charUnicode character
  • isize, usizepointer‑sized
Compound Types
  • tuple(T1, T2, ...)
  • array[T; N]
  • slice&[T]
  • structfields
  • enumvariants
  • Stringheap‑allocated
  • &strstring slice
  • Vec<T>dynamic array
  • HashMap<K, V>key‑value

Type Conversion

let x = 42;
let y = x as f64;           // cast

let s = String::from("123");
let n: i32 = s.parse().unwrap();

Control Flow

if / else

if x > 0 {
    println!("positive");
} else if x < 0 {
    println!("negative");
} else {
    println!("zero");
}

// If as expression
let result = if x > 0 { "positive" } else { "negative" };

match

match value {
    1 => println!("one"),
    2 => println!("two"),
    3..=10 => println!("3-10"),
    _ => println!("other"),
}

// Match with destructuring
match person {
    Person { name, age: 25 } => println!("{} is 25", name),
    Person { name, .. } => println!("{} is other age", name),
}

// Option match
match optional {
    Some(value) => println!("got: {}", value),
    None => println!("nothing"),
}

// Result match
match result {
    Ok(val) => println!("success: {}", val),
    Err(e) => println!("error: {}", e),
}

Loops

// loop (infinite)
loop {
    println!("running...");
    break;
}

// while
while condition {
    println!("running...");
}

// for (range)
for i in 0..10 {
    println!("{}", i);
}

// for (inclusive)
for i in 0..=10 {
    println!("{}", i);
}

// for over iterators
for item in vec.iter() {
    println!("{}", item);
}

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

Ownership & Borrowing

// Ownership rules
let s1 = String::from("hello");
let s2 = s1;  // s1 moved, cannot use

// Clone (deep copy)
let s1 = String::from("hello");
let s2 = s1.clone();

// Borrowing (references)
let s = String::from("hello");
let len = calculate_length(&s);  // borrow s (immutable)

// Mutable reference
let mut s = String::from("hello");
change(&mut s);  // borrow mutably

// Dangling references (prevented at compile time)
{
    let r;
    {
        let x = 5;
        r = &x;  // error: x doesn't live long enough
    }
}

// Slices
let s = String::from("hello world");
let hello = &s[0..5];
let world = &s[6..11];

Structs

struct Person {
    name: String,
    age: u32,
    city: String,
}

// Create instance
let person = Person {
    name: String::from("Alice"),
    age: 25,
    city: String::from("Delhi"),
};

// Access fields
println!("{}", person.name);

// Tuple struct
struct Point(i32, i32);
let p = Point(10, 20);

// Unit struct
struct Unit;

// Impl methods
impl Person {
    fn greet(&self) -> String {
        format!("Hello, {}", self.name)
    }

    fn birthday(&mut self) {
        self.age += 1;
    }

    fn new(name: String, age: u32, city: String) -> Self {
        Self { name, age, city }
    }
}

Enums

enum Status {
    Active,
    Inactive,
    Pending,
}

// Enum with data
enum Result<T, E> {
    Ok(T),
    Err(E),
}

// Enum with different types
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(u8, u8, u8),
}

// Use enum
let status = Status::Active;
let msg = Message::Write(String::from("hello"));

// Option
let x: Option<i32> = Some(5);
let y: Option<i32> = None;

// Result
let success: Result<u32, &str> = Ok(200);
let error: Result<u32, &str> = Err("failed");

Traits

// Define trait
trait Greeter {
    fn greet(&self) -> String;

    fn farewell(&self) -> String {
        String::from("Goodbye")
    }
}

// Implement trait
impl Greeter for Person {
    fn greet(&self) -> String {
        format!("Hello, {}!", self.name)
    }
}

// Trait as parameter
fn say_hello(item: &impl Greeter) {
    println!("{}", item.greet());
}

// Trait bound syntax
fn say_hello<T: Greeter>(item: &T) {
    println!("{}", item.greet());
}

// Derive traits
#[derive(Debug, Clone, PartialEq)]
struct User {
    name: String,
    age: u32,
}

Error Handling

// Result type
use std::fs::File;
use std::io::ErrorKind;

fn open_file() {
    let file_result = File::open("file.txt");
    let file = match file_result {
        Ok(file) => file,
        Err(e) => match e.kind() {
            ErrorKind::NotFound => File::create("file.txt").unwrap(),
            other => panic!("Error: {:?}", other),
        },
    };
}

// Unwrap / expect
let file = File::open("file.txt").unwrap();
let file = File::open("file.txt").expect("Failed to open file");

// ? operator (propagate error)
fn read_file() -> Result<String, std::io::Error> {
    let mut s = String::new();
    File::open("file.txt")?.read_to_string(&mut s)?;
    Ok(s)
}

// Custom error type
use std::fmt;

#[derive(Debug)]
struct MyError {
    code: u32,
    message: String,
}

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "error {}: {}", self.code, self.message)
    }
}

impl std::error::Error for MyError {}

// Panic
panic!("something went wrong");

Concurrency

use std::thread;
use std::time::Duration;
use std::sync::mpsc;
use std::sync::{Arc, Mutex};

// Spawn thread
let handle = thread::spawn(|| {
    for i in 0..5 {
        println!("thread: {}", i);
        thread::sleep(Duration::from_millis(100));
    }
});

handle.join().unwrap();

// Move data to thread
let data = vec![1, 2, 3];
let handle = thread::spawn(move || {
    println!("data: {:?}", data);
});

// Channel (mpsc)
let (tx, rx) = mpsc::channel();

thread::spawn(move || {
    tx.send("Hello").unwrap();
});

let received = rx.recv().unwrap();

// Mutex
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = thread::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());

Collections

Vec

let mut v = vec![1, 2, 3];
v.push(4);
v.pop();

// Iterate
for i in &v {
    println!("{}", i);
}

// Get
let first = v.get(0);  // Option
let first = &v[0];     // panics if out of bounds

HashMap

use std::collections::HashMap;

let mut map = HashMap::new();
map.insert("Alice", 25);
map.insert("Bob", 30);

// Get
let age = map.get("Alice");   // Option

// Iterate
for (key, value) in &map {
    println!("{}: {}", key, value);
}

// Entry API
map.entry("Charlie").or_insert(35);

Modules & Crates

// module.rs
mod utils;

// Nested module
mod math {
    pub fn add(a: i32, b: i32) -> i32 {
        a + b
    }
}

// Use
use utils::helper;
use math::add;

// Re‑export
pub use math::add;

// External crate
use serde::{Serialize, Deserialize};

// Cargo.toml dependencies
[dependencies]
serde = "1.0"
rand = "0.8"

Common Standard Library

String
  • len()
  • is_empty()
  • push_str(s)
  • push(c)
  • contains(s)
  • replace(old, new)
  • split(sep)
  • trim()
  • to_uppercase()
  • to_lowercase()
Iterator
  • iter()immutable
  • iter_mut()mutable
  • into_iter()consumes
  • map(f)
  • filter(f)
  • fold(acc, f)
  • collect()
  • enumerate()
  • zip(other)
  • take(n)
  • skip(n)

Testing

// test module
#[cfg(test)]
mod tests {
    #[test]
    fn test_add() {
        assert_eq!(add(2, 3), 5);
    }

    #[test]
    fn test_add_fail() {
        assert_ne!(add(2, 3), 4);
    }

    #[test]
    #[should_panic(expected = "division by zero")]
    fn test_division_panic() {
        divide(1, 0);
    }
}

// Run tests
// cargo test

Best Practices

  • Use cargo fmt to format code.
  • Use cargo clippy for linting.
  • Prefer Result over unwrap() in production code.
  • Use derive for common traits (Debug, Clone, PartialEq).
  • Use let for immutable by default – only mut when needed.
  • Use &str for parameters that accept string slices.
  • Use Vec<T> over arrays for dynamic collections.
  • Use Option for nullable values instead of null.
  • Use Result for operations that can fail.
  • Use match for exhaustive pattern matching.
  • Use cargo for building, testing, and dependencies.
  • Follow the Rust project structuresrc/, tests/, examples/.
📌 Quick Reference
Check Rust version: rustc --version
Create new project: cargo new project
Build project: cargo build
Run project: cargo run
Run tests: cargo test
Format code: cargo fmt
Lint code: cargo clippy
← Back to All Cheatsheets