Rust Cheatsheet

Structs

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

Defining Structs

// Named-field struct
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

// Tuple struct
struct Color(i32, i32, i32);
struct Point(f64, f64, f64);

// Unit struct (no fields)
struct AlwaysEqual;

Instantiating Structs

let user1 = User {
    email: String::from("alice@example.com"),
    username: String::from("alice"),
    active: true,
    sign_in_count: 1,
};

// Field shorthand — when variable name matches field name
let email = String::from("bob@example.com");
let username = String::from("bob");
let user2 = User {
    email,    // equivalent to email: email
    username,
    active: true,
    sign_in_count: 0,
};

// Struct update syntax — fill remaining fields from another instance
let user3 = User {
    email: String::from("carol@example.com"),
    ..user1   // take remaining fields from user1 (user1 may be partially moved)
};

// Tuple struct
let black = Color(0, 0, 0);
let origin = Point(0.0, 0.0, 0.0);
let r = black.0;   // access by index

// Unit struct
let unit = AlwaysEqual;

Accessing and Mutating Fields

let mut user = User {
    email: String::from("alice@example.com"),
    username: String::from("alice"),
    active: true,
    sign_in_count: 0,
};

// Access
println!("{}", user.email);
println!("{}", user.username);

// Mutate (entire struct must be mut)
user.email = String::from("alice@new.com");
user.sign_in_count += 1;

Rust does not allow marking individual fields as mut — the whole binding must be mutable.

impl Blocks — Methods

struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    // Associated function (no self — called as Rectangle::new())
    fn new(width: f64, height: f64) -> Self {
        Rectangle { width, height }
    }

    fn square(size: f64) -> Self {
        Rectangle { width: size, height: size }
    }

    // Method — immutable borrow of self
    fn area(&self) -> f64 {
        self.width * self.height
    }

    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }

    fn is_larger_than(&self, other: &Rectangle) -> bool {
        self.area() > other.area()
    }

    // Mutable method
    fn scale(&mut self, factor: f64) {
        self.width *= factor;
        self.height *= factor;
    }

    // Consuming method
    fn rotated(self) -> Rectangle {
        Rectangle { width: self.height, height: self.width }
    }
}

let rect = Rectangle::new(10.0, 5.0);
println!("Area: {}", rect.area());           // 50.0
println!("Perimeter: {}", rect.perimeter()); // 30.0

let mut r = Rectangle::new(4.0, 3.0);
r.scale(2.0);   // now 8.0 × 6.0
let r2 = r.rotated();  // r consumed, r2 has swapped dimensions

Multiple impl Blocks

impl Rectangle {
    fn area(&self) -> f64 { self.width * self.height }
}

// Additional impl block — allowed, useful for organizing code
impl Rectangle {
    fn debug_print(&self) {
        println!("{}x{}", self.width, self.height);
    }
}

Deriving Traits

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 1, y: 2 };
let p2 = p1.clone();
println!("{:?}", p1);       // Debug: Point { x: 1, y: 2 }
println!("{:#?}", p1);      // Pretty-print
assert_eq!(p1, p2);         // PartialEq
let p0: Point = Point::default();  // Default: { x: 0, y: 0 }

// Common derivable traits:
// Debug — {:?} formatting
// Clone — .clone() method
// Copy — implicit copy on assignment (requires Clone)
// PartialEq — == and !=
// Eq — full equivalence (requires PartialEq, no NaN-like values)
// PartialOrd — < > <= >= (requires PartialEq)
// Ord — total ordering (requires PartialOrd + Eq)
// Hash — use as HashMap key (requires Eq)
// Default — zero/empty value via Default::default()

Implementing Display

use std::fmt;

struct Point { x: f64, y: f64 }

impl fmt::Display for Point {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

let p = Point { x: 1.0, y: 2.5 };
println!("{}", p);   // (1, 2.5)
let s = p.to_string();  // to_string() is free when Display is implemented

Implementing Traits on Structs

use std::ops::{Add, Mul, Neg};

#[derive(Debug, Clone, Copy, PartialEq)]
struct Vec2 { x: f64, y: f64 }

impl Vec2 {
    fn new(x: f64, y: f64) -> Self { Vec2 { x, y } }
    fn dot(&self, other: &Vec2) -> f64 { self.x * other.x + self.y * other.y }
    fn length(&self) -> f64 { (self.x * self.x + self.y * self.y).sqrt() }
}

impl Add for Vec2 {
    type Output = Vec2;
    fn add(self, other: Vec2) -> Vec2 {
        Vec2::new(self.x + other.x, self.y + other.y)
    }
}

impl Neg for Vec2 {
    type Output = Vec2;
    fn neg(self) -> Vec2 { Vec2::new(-self.x, -self.y) }
}

impl Mul<f64> for Vec2 {
    type Output = Vec2;
    fn mul(self, scalar: f64) -> Vec2 {
        Vec2::new(self.x * scalar, self.y * scalar)
    }
}

let a = Vec2::new(1.0, 2.0);
let b = Vec2::new(3.0, 4.0);
let c = a + b;    // Vec2 { x: 4.0, y: 6.0 }

Struct Visibility

pub struct PublicStruct {
    pub public_field: String,       // accessible anywhere
    private_field: i32,             // only within the module
    pub(crate) crate_field: bool,   // accessible within the crate
    pub(super) super_field: f64,    // accessible in parent module
}

// Even if the struct is pub, private fields limit construction from outside:
// External code cannot do: PublicStruct { private_field: 42, ... }
// Provide constructor associated functions for that:
impl PublicStruct {
    pub fn new(s: String, n: i32) -> Self {
        PublicStruct {
            public_field: s,
            private_field: n,
            crate_field: true,
            super_field: 0.0,
        }
    }
}

Builder Pattern

#[derive(Debug)]
struct RequestBuilder {
    url: String,
    method: String,
    timeout: u64,
    headers: Vec<(String, String)>,
}

impl RequestBuilder {
    fn new(url: impl Into<String>) -> Self {
        RequestBuilder {
            url: url.into(),
            method: "GET".to_string(),
            timeout: 30,
            headers: Vec::new(),
        }
    }

    fn method(mut self, m: impl Into<String>) -> Self {
        self.method = m.into();
        self
    }

    fn timeout(mut self, secs: u64) -> Self {
        self.timeout = secs;
        self
    }

    fn header(mut self, key: impl Into<String>, val: impl Into<String>) -> Self {
        self.headers.push((key.into(), val.into()));
        self
    }

    fn build(self) -> RequestBuilder { self }
}

let req = RequestBuilder::new("https://api.example.com")
    .method("POST")
    .timeout(60)
    .header("Content-Type", "application/json")
    .build();

Newtype Pattern

Wrap a type in a single-field tuple struct to create a distinct type:

struct Meters(f64);
struct Kilograms(f64);

fn travel(distance: Meters) {
    println!("Travelling {} meters", distance.0);
}

let m = Meters(5.0);
let k = Kilograms(70.0);
travel(m);
// travel(k);  // compile error — type safety!

// Implement Display for a foreign type by wrapping it
use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}]", self.0.join(", "))
    }
}

Struct Memory Layout

// Fields are laid out in declaration order (by default)
// Use #[repr(C)] for C-compatible layout
// Use #[repr(packed)] to remove padding
// Use #[repr(align(N))] to set alignment

#[repr(C)]
struct CStruct {
    x: u8,     // 1 byte
    y: u32,    // 4 bytes (3 bytes padding before this with default repr)
}

// std::mem utilities
use std::mem;
mem::size_of::<Rectangle>()   // size in bytes
mem::align_of::<Rectangle>()  // alignment in bytes
mem::size_of_val(&rect)        // size of a value