pub struct SlotData { /* private fields */ }Expand description
Dense Vec indexed by slot_id — the bridge between Rust page handlers and the IR walker.
Handlers create a SlotData, populate it with values (title, user name, nav items, etc.), then the walker reads slot values when it encounters DYN_TEXT, DYN_ATTR, SHOW_IF, LIST opcodes.
Implementations§
Source§impl SlotData
impl SlotData
Sourcepub fn new(capacity: usize) -> Self
pub fn new(capacity: usize) -> Self
Create a new SlotData with capacity Null-initialized slots.
This is the only constructor that can be undersized relative to a
module’s slot table. Prefer SlotData::new_from_defaults or
SlotData::from_json, which size themselves from the module; new
is for tests and for callers that know their own slot count.
Sourcepub fn set(&mut self, slot_id: u16, value: SlotValue)
pub fn set(&mut self, slot_id: u16, value: SlotValue)
Set a slot value, growing the backing storage if slot_id is past the
end (new entries are Null).
This used to be a silent no-op when out of bounds, which made a LIST
whose item_slot_id exceeded the SlotData length render every row
identically with no error at all. Growing is cheap, and a write outside
the module’s declared slot table cannot reach here from a parsed module
— IrModule::validate rejects an opcode naming an undeclared slot at
parse time — so the branch only catches a caller that sized its own
SlotData too small, and warns under the tracing feature.
Verified by: crates/forma-ir/src/slot.rs > “set_grows_instead_of_silently_dropping” Verified by: crates/forma-ir/src/parser.rs > “validate_rejects_list_item_slot_not_in_table”
Sourcepub fn replace(&mut self, slot_id: u16, value: SlotValue) -> SlotValue
pub fn replace(&mut self, slot_id: u16, value: SlotValue) -> SlotValue
Set a slot value and return the previous one.
This is the primitive the walker’s LIST loop is built on: it binds the
row’s item (and any PROP the body extracts from it) by swapping values
in, then swaps the saved originals back when the row ends. That keeps
per-row scoping without the deep SlotData clone the loop used to take,
which made a list cost O(rows x slots) instead of O(rows).
Verified by: crates/forma-ir/tests/list_scaling.rs > “list_walk_allocations_are_linear_in_row_count”
Sourcepub fn get(&self, slot_id: u16) -> &SlotValue
pub fn get(&self, slot_id: u16) -> &SlotValue
Get a reference to a slot value. Returns &Null if out of bounds.
Sourcepub fn get_text(&self, slot_id: u16) -> Option<&str>
pub fn get_text(&self, slot_id: u16) -> Option<&str>
Get the text content of a slot. Returns Some(&str) if Text, None otherwise.
Sourcepub fn from_json(json_str: &str, module: &IrModule) -> Result<Self, IrError>
pub fn from_json(json_str: &str, module: &IrModule) -> Result<Self, IrError>
Create SlotData from a named-key JSON string, resolving names to slot IDs via the module’s string table and slot table.
The JSON must be an object (e.g., {"title": "Hello", "count": 42}).
Each key is resolved against the slot table: the slot entry’s name_str_idx
is looked up in the string table to find the slot name. If it matches a JSON
key, the JSON value is converted to a SlotValue and stored at that slot_id.
Unknown JSON keys (not in the slot table) are silently ignored.
Starts from slot table defaults so missing keys retain their defaults.
JSON numbers become IEEE-754 f64 values. Decimal spellings use
correctly rounded parsing, so finite f64 values serialized to JSON
preserve their bits, including negative zero. This does not make all
integers above 2^53 exact. Island state serialization subsequently
canonicalizes negative zero to zero under the Serialize9 contract.
Sourcepub fn new_from_defaults(table: &SlotTable) -> Self
pub fn new_from_defaults(table: &SlotTable) -> Self
Create SlotData pre-populated from the IR slot table defaults. Server-sourced slots with no default -> Null. Client-sourced slots with defaults -> parsed from default_bytes.