Structs and impl Blocks

Rust has no classes. The equivalent is a struct for data and an impl block for methods — kept deliberately separate.

The struct

A struct is a named group of fields:

#![allow(unused)]
fn main() {
pub struct Cpu {
    pub v:     [u8; 16],    // general-purpose registers V0–VF
    pub i:     u16,         // index register
    pub pc:    u16,         // program counter
    pub sp:    u8,          // stack pointer
    pub stack: [u16; 16],   // return address stack
}
}

Each field has a name and a type. pub makes a field visible outside the module — without it, the field is private by default.

The impl block

Methods live in a separate impl block:

#![allow(unused)]
fn main() {
impl Cpu {
    pub fn new() -> Self {
        Cpu {
            v:     [0; 16],
            i:     0,
            pc:    0x200,   // programs start at 0x200
            sp:    0,
            stack: [0; 16],
        }
    }

    pub fn step(&mut self) {
        // fetch, decode, execute one instruction
    }
}
}

new() is a static constructor — it takes no self. step() takes &mut self because it modifies the CPU state.

&self vs &mut self

This distinction is enforced at compile time:

  • &self — read-only access to the struct's fields
  • &mut self — read and write access

If a method with &self tries to modify a field, the compiler rejects it. This prevents accidental mutations and is part of Rust's core ownership system.

OOP comparison

OOPRust
classstruct + impl
constructornew() (convention, not a keyword)
methodfunction in impl
this / self&self or &mut self
inheritancedoesn't exist — use Traits
private/publicpub per item

Why separate data from behavior?

It makes each concern independently visible. Looking at a struct, you see exactly what data it holds. Looking at an impl, you see exactly what it can do. You can have multiple impl blocks — useful for putting tests in a separate file — and you can implement traits in their own blocks.


In the emulator: Cpu, Memory, and Display are all structs with their own impl blocks. Cpu owns a Memory and a Display as fields. The CHIP-8 Registers chapter describes what each field of Cpu represents in hardware terms. The Constructors chapter explains why new() is needed for Cpu specifically.