Vec<T> — Dynamic Arrays

Vec<T> is a growable array that lives on the heap. Unlike [T; N], its size is not known at compile time — it can grow as elements are added.

Creating a Vec

#![allow(unused)]
fn main() {
// pre-filled with a value
let buffer = vec![0u32; 64 * 32];  // 2048 zeros

// from an iterator
let sprite: Vec<u8> = (0..n)
    .map(|row| self.memory.read(self.i + row as u16))
    .collect();
}

.collect() consumes an iterator and gathers its values into a collection. The type annotation Vec<u8> tells the compiler which collection to build.

Vec vs array vs slice

TypeSizeLocationUse case
[T; N]fixed, compile-timestackregisters, framebuffer
&[T]unknown, compile-timeanywherefunction parameters, views
Vec<T>dynamic, runtimeheapcollections that grow or shrink

In the emulator, Vec<u8> is used for sprites because their size (n rows) comes from the opcode — it is only known at runtime. A fixed array cannot represent this.

Dereferencing to a slice

Vec<T> automatically coerces to &[T], so a Vec can be passed anywhere a slice is expected:

#![allow(unused)]
fn main() {
fn draw_sprite(sprite: &[u8]) { ... }

let sprite: Vec<u8> = vec![0xF0, 0x90];
draw_sprite(&sprite);  // Vec coerces to &[u8]
}

Accessing elements

#![allow(unused)]
fn main() {
let v = vec![10u8, 20, 30];

v[0]     // 10 — panics if out of bounds
v.get(0) // Some(10) — safe, returns Option
v.len()  // 3
}

In the emulator: Vec<u8> is used in the DXYN opcode to build the sprite byte array before passing it to draw_sprite. Vec<u32> is used in main.rs as the pixel buffer for minifb. See DRW — Drawing Sprites and The Main Loop. For fixed-size collections, see Primitive Types and Arrays. For passing variable-length data to functions, see Slices and Ranges.