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
| Type | Size | Location | Use case |
|---|---|---|---|
[T; N] | fixed, compile-time | stack | registers, framebuffer |
&[T] | unknown, compile-time | anywhere | function parameters, views |
Vec<T> | dynamic, runtime | heap | collections 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 theDXYNopcode to build the sprite byte array before passing it todraw_sprite.Vec<u32>is used inmain.rsas the pixel buffer forminifb. 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.