1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Array-spill geometry and the blocked-spill policy (plan item 3.5, issue
//! #537), shared between the recalc engine ([`crate::recalc`]) and the
//! spill-resolving cell accessor ([`Workbook::get`](crate::Workbook::get)).
//!
//! # The model (schema spec §5)
//!
//! A formula whose result is an `m × n` array is a **spill anchor**: it stores
//! the full array (schema spec §6 `array`) and *occupies* the rectangle
//! `(r..r+m-1, c..c+n-1)` anchored at the formula cell `(r, c)`, in reading
//! order. The non-anchor cells of that rectangle are **spilled** cells: they
//! are a derived view, never authored and **never serialized** — only the
//! anchor's array is on the wire (schema spec §5, superseding the plan's
//! "spilled marker" sketch). A consumer reconstructs the grid by the five-line
//! rule in §5; this module is that rule.
//!
//! # Blocked spill (Sheets semantics)
//!
//! A spill is **blocked** — the anchor takes the Sheets blocked-spill error
//! ([`BLOCKED_SPILL_ERROR`]) and **no array is stored** — when, per §5:
//!
//! - any non-anchor cell of the rectangle is *occupied* (an authored literal or
//! formula, or a cell already claimed by another spill resolved earlier this
//! recalc), or
//! - the rectangle would extend **beyond the sheet's address bounds** (limits
//! ADR) — treated as blocked pending fixture verification (§5).
//!
//! Spill resolution runs in deterministic recalc order (topological, tie-broken
//! by sheet position → row → column — scope ADR Decision 3), so two anchors
//! competing for the same cell resolve reproducibly: the earlier anchor wins
//! and the later one blocks.
//!
//! A 1×1 array never reaches here: it is collapsed to its scalar before storage
//! (schema spec §6), so [`Value::Array`](crate::Value::Array) always describes a
//! spill of at least two cells.
use crateAddress;
use crate;
/// The Sheets blocked-spill error code (schema spec §12 edge-case 1: Sheets
/// reports a blocked array expansion as `#REF!`).
///
/// A dedicated workbook **blocked-spill** fixture is not yet exported into the
/// core crate's fixture tree (the P3.6 set committed there covers cross-sheet,
/// named-range, and date-type rows — see `crates/core/tests/fixtures/`), so this
/// exact code is **not fixture-pinned in this crate**; the schema spec's §12
/// worked example is the authority used here, and the in-repo spill tests assert
/// the *behavior* (a blocked anchor takes this error, stores no array, and
/// leaves the target cells unspilled). The code is re-verified against a
/// `spill` fixture when one lands in core (issue note, mirrors
/// [`crate::recalc::CIRCULAR_ERROR`]'s handling).
pub const BLOCKED_SPILL_ERROR: &str = "#REF!";
/// The rectangle an `rows × cols` array spills into, anchored at `anchor`
/// (reading order): inclusive corners `(anchor.row, anchor.column)` ..
/// `(anchor.row + rows - 1, anchor.column + cols - 1)`.
///
/// Returns `None` if the rectangle would leave the sheet's address bounds (a
/// blocked, out-of-bounds spill — §5). `rows`/`cols` are the dimensions of a
/// stored `array` value, hence always ≥ 1 (and, jointly, ≥ 2 — §6).
/// An in-bounds spill rectangle: the geometry of one anchor's reconstructed
/// array. Cheap to copy; membership and indexing are `O(1)`.