Skip to main content

Workbook

Struct Workbook 

Source
pub struct Workbook { /* private fields */ }
Expand description

An engine-locked spreadsheet workbook — a pure value object (no hidden state, no callbacks). Schema spec §2.

All four fields are always serialized, even when empty. Field declaration order (engine, names, sheets, version) matches canonical (JCS) key order.

Implementations§

Source§

impl Workbook

Source

pub fn set( &mut self, sheet: &str, addr: Address, input: CellInput, ) -> Result<Option<Cell>, WorkbookError>

Writes input at addr on the sheet named sheet (case-insensitive), returning the cell previously there (if any).

A literal is stored as a value-only cell; a formula is stored verbatim (with its leading =) carrying a Value::Empty result until the next recalc — set validates only the formula’s syntax against the workbook’s locked engine, never evaluating it (recalc is P3.3).

Enforces, eagerly, the per-mutation caps of scope ADR Decision 5: a formula’s length, a text/array value’s size, and — when the write introduces a new populated cell — the per-workbook cell count.

Errors if the sheet does not exist, the input is an empty literal (schema spec §4 — clear instead), the formula is syntactically invalid for the locked engine, or any cap would be exceeded.

Source

pub fn get(&self, sheet: &str, addr: Address) -> Option<&Cell>

The authored cell at addr on the sheet named sheet (case-insensitive), or None if no cell is authored there.

This returns only authored cells — a literal or a formula physically present in cells. A spilled cell (one materialized by a spill anchor, schema spec §5) is not authored and has no Cell to borrow, so get returns None for it; use resolved to read the effective value at any address (authored or spilled) and learn the spill anchor. Keeping get authored-only preserves the structural distinguishability rule of §5 (a cell is authored iff it has an entry).

Source

pub fn resolved(&self, sheet: &str, addr: Address) -> Option<Resolved>

The effective value at addr on the sheet named sheet (case-insensitive), resolving through array spills (schema spec §5).

Returns None only if addr is genuinely empty — neither authored nor covered by a spill. Otherwise the returned Resolved carries the value and, for a spilled cell, the anchor it spilled from (the runtime spilledFrom view of §5 — never serialized). For an authored cell anchor is None. A blocked-spill anchor is just an authored formula cell whose value is the blocked-spill error, so it resolves as an ordinary authored cell with no anchor.

Resolution reads the stored grid (the last recalc’s results): a spilling anchor stores its full array (§6), and this reconstructs the spilled element by the five-line rule of §5. It does not recalc.

Source

pub fn spill_anchor(&self, sheet: &str, addr: Address) -> Option<Address>

The spill anchor that materializes addr on the sheet named sheet (case-insensitive), or None if addr is authored or empty (schema spec §5). Convenience over resolved when only the anchor identity (the spilledFrom view) is needed.

Source

pub fn clear(&mut self, sheet: &str, addr: Address) -> Option<Cell>

Removes the cell at addr on the sheet named sheet (case-insensitive), returning it if present. Clearing is removing the entry, never writing an empty value (schema spec §4). Returns None if the sheet or cell is absent.

Source

pub fn total_cells(&self) -> usize

The total number of populated cells across every sheet — the quantity the per-workbook cell cap (scope ADR Decision 5) bounds.

Source

pub fn define_name( &mut self, name: &str, r: &str, ) -> Result<&NamedRange, WorkbookError>

Defines a new workbook-scoped named range name pointing at the canonical reference r (Sheet!A1 / Sheet!A1:B2), returning the stored NamedRange.

Validates everything from_json checks for a name (schema spec §7): the name’s shape, the ref’s canonical form, that the target sheet exists (no dangling ref), that the name does not already exist (case-insensitively), and that the named-range cap (Decision 5) is not exceeded. To replace an existing name use redefine_name.

Source

pub fn redefine_name( &mut self, name: &str, r: &str, ) -> Result<&NamedRange, WorkbookError>

Redefines the existing named range name (case-insensitive) to point at the canonical reference r, returning the updated NamedRange. The name’s identity and original casing are preserved; only the ref changes.

Validates the ref exactly as define_name does, including that the target sheet exists (no dangling ref). Errors if no name currently matches name (case-insensitively) or if the ref is not a valid canonical reference to an existing sheet.

Source

pub fn remove_name(&mut self, name: &str) -> Option<NamedRange>

Removes the named range name (case-insensitive), returning it if it existed, or None otherwise.

Source

pub fn name(&self, name: &str) -> Option<&NamedRange>

The named range called name (case-insensitive), or None. Listing is names.

Source§

impl Workbook

Source

pub fn recalc(&mut self, ctx: &RecalcContext) -> Vec<Change>

Recomputes every formula cell in dependency order against ctx, writing each new result back into the grid and returning the ordered list of cells whose value changed.

Formula cells are evaluated in topological order (precedents first), so each reads its inputs already current. Cells on a dependency cycle — and any cell that cannot be ordered because it (transitively) reads one — take the circular-dependency error (CIRCULAR_ERROR); recalc always terminates. Volatile functions are pinned by ctx (scope ADR Decision 3).

Changes are returned sorted by (sheet tab index, row, column).

Source

pub fn recalc_incremental( &mut self, ctx: &RecalcContext, edited: &[(String, Address)], ) -> Vec<Change>

Recomputes only the formula cells affected by an edit and returns the ordered changes.

edited lists the cells a mutation touched (the cell written, or — for a named-range retarget — the name’s old and new target cells; callers pass whatever changed). The recalc closure is the transitive direct_dependents of those cells, plus every volatile formula cell (always dirty, scope ADR Decision 3). Everything outside the closure keeps its stored result.

The result is identical to the subset of recalc’s output for the same edits — the incremental ≡ full guarantee.

Source§

impl Workbook

Source

pub fn new(engine: EngineFlavor) -> Self

Creates an empty workbook locked to engine.

The engine flavor is required at creation and immutable for the workbook’s lifetime (ADR 2026-04-27-engine-flavor-explicit-everywhere): there is no default and no setter.

Source

pub fn engine(&self) -> EngineFlavor

The engine flavor every formula in this workbook targets.

Source

pub fn version(&self) -> &str

The schema version of this workbook document.

Source

pub fn sheets(&self) -> &[Worksheet]

The worksheets, in tab order (array position is tab position).

Source

pub fn sheets_mut(&mut self) -> &mut Vec<Worksheet>

Mutable access to the worksheets.

Source

pub fn names(&self) -> &[NamedRange]

The workbook-scoped named ranges.

Source

pub fn names_mut(&mut self) -> &mut Vec<NamedRange>

Mutable access to the named ranges.

Source

pub fn sheet(&self, name: &str) -> Option<&Worksheet>

The worksheet named name (case-insensitive, simple case folding per schema spec §2), or None if no sheet matches.

Source

pub fn sheet_mut(&mut self, name: &str) -> Option<&mut Worksheet>

Mutable access to the worksheet named name (case-insensitive).

Source

pub fn sheet_index(&self, name: &str) -> Option<usize>

The tab position (0-based array index) of the sheet named name (case-insensitive per schema spec §2), or None if no sheet matches.

Source

pub fn add_sheet(&mut self, sheet: Worksheet) -> Result<usize, WorkbookError>

Appends sheet after the last tab and returns its 0-based position.

Errors if the name collides with an existing sheet under simple case folding (schema spec §2), is empty or too long (schema spec §3), or would exceed the per-workbook sheet cap (scope ADR Decision 5).

Source

pub fn insert_sheet( &mut self, index: usize, sheet: Worksheet, ) -> Result<(), WorkbookError>

Inserts sheet at tab position index, shifting later tabs right. index == sheets().len() appends. Position semantics: array index is tab position (schema spec §2 — order is significant).

Errors on a duplicate name (case-insensitive, §2), an empty/too-long name (§3), the sheet cap (Decision 5), or index out of 0..=len.

Source

pub fn remove_sheet(&mut self, name: &str) -> Option<Worksheet>

Removes and returns the sheet named name (case-insensitive), shifting later tabs left, or None if no sheet matches.

A workbook-scoped named range may now dangle to the removed sheet; the dangling-ref invariant is re-checked at to_json / from_json (schema spec §7).

Source

pub fn rename_sheet( &mut self, from: &str, to: &str, ) -> Result<(), WorkbookError>

Renames the sheet currently named from (case-insensitive) to to.

A pure case change of the same sheet is allowed (it does not collide with itself). Errors if from does not exist, if to is empty/too long (§3), or if to collides with a different sheet (§2).

Source

pub fn move_sheet( &mut self, from: usize, to: usize, ) -> Result<(), WorkbookError>

Moves the sheet at tab position from to position to, shifting the sheets in between (schema spec §2 — array position is tab position). Errors if either index is out of 0..len.

Source

pub fn from_json(bytes: &[u8]) -> Result<Self, WorkbookError>

Parses a workbook from JSON bytes, enforcing every document-level rule of the schema (schema spec §1–§10) and the resource limits of the scope ADR (Decision 5).

Accepts any schema-valid JSON — pretty-printed, reordered keys, extra whitespace are all fine; only the content must be valid (schema spec §8: non-canonical-but-valid input is accepted, output is always canonical). Beyond the serde layer’s checks (unknown fields, value encodings incl. NaN/Inf and -0, empty-literal, exact version match), this enforces the rules serde cannot express:

  • §1 duplicate object keys are rejected; a UTF-8 BOM and invalid UTF-8 are rejected at the byte boundary (hence &[u8], not &str);
  • §2/§3 sheet names are non-empty, ≤ 100 scalar values, and unique under Unicode simple case folding;
  • §3 cell keys match ^[A-Z]{1,3}[1-9][0-9]{0,7}$ and lie within the address bounds;
  • §5 spill rectangles are document-valid (no authored cell inside an anchor’s rectangle, no overlapping rectangles, none out of bounds);
  • §7 named-range names and refs are valid and canonical, names are unique case-insensitively, and no ref dangles to a missing sheet;
  • Decision 5 input size and all structural limits are enforced.
Source

pub fn to_json(&self) -> Result<String, WorkbookError>

Serializes the workbook to its canonical RFC 8785 (JCS) byte form (schema spec §8): one line, no insignificant whitespace, no trailing newline, object keys sorted by UTF-16 code units, ECMAScript number formatting, names sorted by name.

Errors if a value is non-finite (forbidden, schema spec §8.4) or if the canonical bytes exceed the 100 MiB cap (scope ADR Decision 5).

Trait Implementations§

Source§

impl Clone for Workbook

Source§

fn clone(&self) -> Workbook

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Workbook

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Workbook

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Hash for Workbook

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for Workbook

Source§

fn eq(&self, other: &Workbook) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Workbook

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Workbook

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.