Skip to main content

hurray_ffi/field/
layout.rs

1//! Layout-payload fields: identifier range `0x0001_xxxx`.
2//!
3//! The discriminant byte is the layout tag, so an identifier's applicability is
4//! a comparison against the descriptor's own tag and the field space inherits
5//! the layout tag space's reserved and private ranges for free (ADR-039 § 3).
6
7use hurray_core::layout::{LayoutDescriptor, TiledLayout};
8
9use super::{HurrayDescriptorField, U64Source};
10use crate::status::{
11    HurrayStatus, HURRAY_ERR_FIELD_NOT_APPLICABLE, HURRAY_ERR_FIELD_NOT_PRESENT,
12    HURRAY_ERR_INDEX_OUT_OF_BOUNDS,
13};
14
15// ── Field identifiers ─────────────────────────────────────────────────────────
16
17/// Strided (`0x03`) per-dimension strides, in logical elements. Signed array.
18pub const HURRAY_LAYOUT_FIELD_STRIDED_STRIDES: HurrayDescriptorField = 0x0001_0300;
19
20/// Tiled (`0x04`) tile extent per dimension. Unsigned array.
21pub const HURRAY_LAYOUT_FIELD_TILED_TILE_SHAPE: HurrayDescriptorField = 0x0001_0400;
22
23/// Tiled (`0x04`) layout tag governing the order of tiles.
24pub const HURRAY_LAYOUT_FIELD_TILED_OUTER_LAYOUT: HurrayDescriptorField = 0x0001_0401;
25
26/// Tiled (`0x04`) layout tag governing the order of elements within a tile.
27pub const HURRAY_LAYOUT_FIELD_TILED_INNER_LAYOUT: HurrayDescriptorField = 0x0001_0402;
28
29/// Tiled (`0x04`) explicit strides between tiles. Signed array, optional.
30pub const HURRAY_LAYOUT_FIELD_TILED_OUTER_STRIDES: HurrayDescriptorField = 0x0001_0403;
31
32/// Tiled (`0x04`) explicit strides within a tile. Signed array, optional.
33pub const HURRAY_LAYOUT_FIELD_TILED_INNER_STRIDES: HurrayDescriptorField = 0x0001_0404;
34
35/// Tiled (`0x04`) number of nesting levels from `level` downward.
36pub const HURRAY_LAYOUT_FIELD_TILED_DEPTH: HurrayDescriptorField = 0x0001_0405;
37
38/// Morton (`0x05`) per-dimension interleave bit counts. Unsigned array.
39pub const HURRAY_LAYOUT_FIELD_MORTON_BITS: HurrayDescriptorField = 0x0001_0500;
40
41/// COO (`0x06`) stored non-zero count.
42pub const HURRAY_LAYOUT_FIELD_COO_NNZ: HurrayDescriptorField = 0x0001_0600;
43
44/// COO (`0x06`) whether coordinates are in lexicographic order. `0` or `1`.
45pub const HURRAY_LAYOUT_FIELD_COO_IS_SORTED: HurrayDescriptorField = 0x0001_0601;
46
47/// CSR (`0x07`) stored non-zero count.
48pub const HURRAY_LAYOUT_FIELD_CSR_NNZ: HurrayDescriptorField = 0x0001_0700;
49
50/// CSC (`0x08`) stored non-zero count.
51pub const HURRAY_LAYOUT_FIELD_CSC_NNZ: HurrayDescriptorField = 0x0001_0800;
52
53/// CSF (`0x09`) stored non-zero count.
54pub const HURRAY_LAYOUT_FIELD_CSF_NNZ: HurrayDescriptorField = 0x0001_0900;
55
56/// CSF (`0x09`) mode storage order. Unsigned array.
57pub const HURRAY_LAYOUT_FIELD_CSF_MODE_ORDER: HurrayDescriptorField = 0x0001_0901;
58
59/// Block-paged (`0x0A`) elements per page along the paged axis.
60pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_PAGE_SIZE: HurrayDescriptorField = 0x0001_0A00;
61
62/// Block-paged (`0x0A`) total pages in the shared pool.
63pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_NUM_PAGES: HurrayDescriptorField = 0x0001_0A01;
64
65/// Block-paged (`0x0A`) index of the paged axis.
66pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_PAGED_AXIS: HurrayDescriptorField = 0x0001_0A02;
67
68/// Block-paged (`0x0A`) number of sequences sharing the pool.
69pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_NUM_SEQS: HurrayDescriptorField = 0x0001_0A03;
70
71/// Block-paged (`0x0A`) KV role wire byte: key `0x00`, value `0x01`, fused `0x02`.
72pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_KV_ROLE: HurrayDescriptorField = 0x0001_0A04;
73
74/// Block-paged (`0x0A`) transformer layer index. Optional.
75pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_LAYER_INDEX: HurrayDescriptorField = 0x0001_0A05;
76
77/// Block-paged (`0x0A`) block-table element width: `u32` `0x00`, `u64` `0x01`.
78pub const HURRAY_LAYOUT_FIELD_BLOCK_PAGED_INDEX_TYPE: HurrayDescriptorField = 0x0001_0A06;
79
80/// Composite (`0x0B`) composition rule wire byte.
81pub const HURRAY_LAYOUT_FIELD_COMPOSITE_RULE: HurrayDescriptorField = 0x0001_0B00;
82
83/// Composite (`0x0B`) combine-op wire byte; `0x00` unless the rule is overlay.
84pub const HURRAY_LAYOUT_FIELD_COMPOSITE_COMBINE_OP: HurrayDescriptorField = 0x0001_0B01;
85
86/// Composite (`0x0B`) number of member descriptors following the head.
87pub const HURRAY_LAYOUT_FIELD_COMPOSITE_MEMBER_COUNT: HurrayDescriptorField = 0x0001_0B02;
88
89/// Hilbert (`0x40`) curve order; every dimension equals `2^order`.
90pub const HURRAY_LAYOUT_FIELD_HILBERT_ORDER: HurrayDescriptorField = 0x0001_4000;
91
92/// Hilbert (`0x40`) curve rank.
93pub const HURRAY_LAYOUT_FIELD_HILBERT_RANK: HurrayDescriptorField = 0x0001_4001;
94
95// ── Internal resolution ───────────────────────────────────────────────────────
96
97/// Walks `level` steps down a tiled layout's nesting chain.
98fn tiled_at_level(root: &TiledLayout, level: u32) -> Result<&TiledLayout, HurrayStatus> {
99    let mut current = root;
100    for _ in 0..level {
101        current = match current.inner_tiled.as_deref() {
102            Some(inner) => inner,
103            None => return Err(HURRAY_ERR_INDEX_OUT_OF_BOUNDS),
104        };
105    }
106    Ok(current)
107}
108
109/// Counts nesting levels from `tile` downward, including `tile` itself.
110fn tiled_depth(tile: &TiledLayout) -> u64 {
111    let mut depth = 1;
112    let mut current = tile;
113    while let Some(inner) = current.inner_tiled.as_deref() {
114        depth += 1;
115        current = inner;
116    }
117    depth
118}
119
120/// Rejects a non-zero `level` against a layout that does not nest.
121///
122/// Checked once up front rather than in every arm: `level` is meaningful only
123/// for tiled layouts, and silently ignoring it elsewhere would let a caller
124/// believe it had read a nested level that does not exist.
125fn check_level(layout: &LayoutDescriptor, level: u32) -> Result<(), HurrayStatus> {
126    if level != 0 && !matches!(layout, LayoutDescriptor::Tiled(_)) {
127        return Err(HURRAY_ERR_INDEX_OUT_OF_BOUNDS);
128    }
129    Ok(())
130}
131
132/// Resolves an unsigned scalar field against a layout.
133///
134/// Matching on the `(field, layout)` pair makes the match arms themselves the
135/// applicability check — no separate tag comparison, and no unreachable arm.
136pub(super) fn u64_scalar(
137    layout: &LayoutDescriptor,
138    field: HurrayDescriptorField,
139    level: u32,
140) -> Result<u64, HurrayStatus> {
141    check_level(layout, level)?;
142
143    match (field, layout) {
144        // Tiled
145        (HURRAY_LAYOUT_FIELD_TILED_OUTER_LAYOUT, LayoutDescriptor::Tiled(root)) => {
146            Ok(tiled_at_level(root, level)?.outer_layout as u64)
147        }
148        (HURRAY_LAYOUT_FIELD_TILED_INNER_LAYOUT, LayoutDescriptor::Tiled(root)) => {
149            Ok(tiled_at_level(root, level)?.inner_layout as u64)
150        }
151        (HURRAY_LAYOUT_FIELD_TILED_DEPTH, LayoutDescriptor::Tiled(root)) => {
152            Ok(tiled_depth(tiled_at_level(root, level)?))
153        }
154
155        // Sparse
156        (HURRAY_LAYOUT_FIELD_COO_NNZ, LayoutDescriptor::Coo(l)) => Ok(l.nnz),
157        (HURRAY_LAYOUT_FIELD_COO_IS_SORTED, LayoutDescriptor::Coo(l)) => Ok(l.is_sorted as u64),
158        (HURRAY_LAYOUT_FIELD_CSR_NNZ, LayoutDescriptor::Csr(l)) => Ok(l.nnz),
159        (HURRAY_LAYOUT_FIELD_CSC_NNZ, LayoutDescriptor::Csc(l)) => Ok(l.nnz),
160        (HURRAY_LAYOUT_FIELD_CSF_NNZ, LayoutDescriptor::Csf(l)) => Ok(l.nnz),
161
162        // Block-paged
163        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_PAGE_SIZE, LayoutDescriptor::BlockPaged(l)) => {
164            Ok(l.page_size as u64)
165        }
166        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_NUM_PAGES, LayoutDescriptor::BlockPaged(l)) => {
167            Ok(l.num_pages)
168        }
169        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_PAGED_AXIS, LayoutDescriptor::BlockPaged(l)) => {
170            Ok(l.paged_axis as u64)
171        }
172        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_NUM_SEQS, LayoutDescriptor::BlockPaged(l)) => {
173            Ok(l.num_seqs as u64)
174        }
175        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_KV_ROLE, LayoutDescriptor::BlockPaged(l)) => {
176            Ok(l.kv_role.wire_byte() as u64)
177        }
178        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_LAYER_INDEX, LayoutDescriptor::BlockPaged(l)) => l
179            .layer_index
180            .map(u64::from)
181            .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT),
182        (HURRAY_LAYOUT_FIELD_BLOCK_PAGED_INDEX_TYPE, LayoutDescriptor::BlockPaged(l)) => {
183            Ok(l.block_table_index_type.wire_byte() as u64)
184        }
185
186        // Composite
187        (HURRAY_LAYOUT_FIELD_COMPOSITE_RULE, LayoutDescriptor::Composite(l)) => {
188            Ok(l.rule.rule_byte() as u64)
189        }
190        (HURRAY_LAYOUT_FIELD_COMPOSITE_COMBINE_OP, LayoutDescriptor::Composite(l)) => {
191            Ok(l.rule.combine_op_byte() as u64)
192        }
193        (HURRAY_LAYOUT_FIELD_COMPOSITE_MEMBER_COUNT, LayoutDescriptor::Composite(l)) => {
194            Ok(l.member_count as u64)
195        }
196
197        // Hilbert
198        (HURRAY_LAYOUT_FIELD_HILBERT_ORDER, LayoutDescriptor::Hilbert(l)) => {
199            Ok(l.hilbert_order as u64)
200        }
201        (HURRAY_LAYOUT_FIELD_HILBERT_RANK, LayoutDescriptor::Hilbert(l)) => {
202            Ok(l.hilbert_rank as u64)
203        }
204
205        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
206    }
207}
208
209/// Resolves an unsigned array field against a layout.
210pub(super) fn u64_array<'a>(
211    layout: &'a LayoutDescriptor,
212    field: HurrayDescriptorField,
213    level: u32,
214) -> Result<U64Source<'a>, HurrayStatus> {
215    check_level(layout, level)?;
216
217    match (field, layout) {
218        (HURRAY_LAYOUT_FIELD_TILED_TILE_SHAPE, LayoutDescriptor::Tiled(root)) => {
219            Ok(U64Source::Direct(&tiled_at_level(root, level)?.tile_shape))
220        }
221        (HURRAY_LAYOUT_FIELD_MORTON_BITS, LayoutDescriptor::Morton(l)) => {
222            Ok(U64Source::Widened(&l.morton_bits))
223        }
224        (HURRAY_LAYOUT_FIELD_CSF_MODE_ORDER, LayoutDescriptor::Csf(l)) => {
225            Ok(U64Source::Widened(&l.mode_order))
226        }
227        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
228    }
229}
230
231/// Resolves a signed array field against a layout.
232pub(super) fn i64_array(
233    layout: &LayoutDescriptor,
234    field: HurrayDescriptorField,
235    level: u32,
236) -> Result<&[i64], HurrayStatus> {
237    check_level(layout, level)?;
238
239    match (field, layout) {
240        (HURRAY_LAYOUT_FIELD_STRIDED_STRIDES, LayoutDescriptor::Strided(l)) => Ok(&l.strides),
241        (HURRAY_LAYOUT_FIELD_TILED_OUTER_STRIDES, LayoutDescriptor::Tiled(root)) => {
242            match tiled_at_level(root, level)?.outer_strides.as_ref() {
243                Some(s) => Ok(&s.strides),
244                None => Err(HURRAY_ERR_FIELD_NOT_PRESENT),
245            }
246        }
247        (HURRAY_LAYOUT_FIELD_TILED_INNER_STRIDES, LayoutDescriptor::Tiled(root)) => {
248            match tiled_at_level(root, level)?.inner_strides.as_ref() {
249                Some(s) => Ok(&s.strides),
250                None => Err(HURRAY_ERR_FIELD_NOT_PRESENT),
251            }
252        }
253        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
254    }
255}