Skip to main content

hurray_ffi/field/
section.rs

1//! Optional-section fields: identifier ranges `0x0002_xxxx` through `0x0006_xxxx`.
2//!
3//! Each of the five optional descriptor sections takes one range (ADR-040).
4//! Quantization is the only section with an inner sum type, so it is the only
5//! one that uses the discriminant byte — for the scheme tag, exactly as the
6//! layout range uses the layout tag. The others carry `0x00` there.
7//!
8//! None of these sections is required at any conformance level, so an absent
9//! section is a normal answer: every read returns
10//! [`HURRAY_ERR_FIELD_NOT_PRESENT`] rather than an error when its section is
11//! missing.
12
13use hurray_core::{
14    descriptor::{ExtensionTypeDescriptor, ShardDescriptor, Statistics, TensorDescriptor},
15    QuantizationDescriptor,
16};
17
18use super::{HurrayDescriptorField, U64Source};
19use crate::status::{
20    status_from_core_error, HurrayStatus, HURRAY_ERR_FIELD_NOT_APPLICABLE,
21    HURRAY_ERR_FIELD_NOT_PRESENT, HURRAY_ERR_INDEX_OUT_OF_BOUNDS,
22};
23
24// ── Quantization (0x0002) ─────────────────────────────────────────────────────
25
26/// Quantization scheme tag of the section this descriptor carries: per-tensor
27/// affine `0x01`, per-channel affine `0x02`, per-block affine `0x03`, NF4
28/// `0x04`, MXFP `0x05`.
29///
30/// Read this first: it tells a caller which of the scheme-specific identifiers
31/// below apply. The discriminant byte is `0x00`, which is not a valid scheme
32/// tag, so the slot addresses the section rather than one scheme within it.
33pub const HURRAY_QUANT_FIELD_SCHEME_TAG: HurrayDescriptorField = 0x0002_0000;
34
35/// Per-tensor affine (`0x01`) scale. Real scalar, `float32` on the wire.
36pub const HURRAY_QUANT_FIELD_PER_TENSOR_SCALE: HurrayDescriptorField = 0x0002_0100;
37
38/// Per-tensor affine (`0x01`) zero point. Signed scalar, `int32` on the wire.
39pub const HURRAY_QUANT_FIELD_PER_TENSOR_ZERO_POINT: HurrayDescriptorField = 0x0002_0101;
40
41/// Per-channel affine (`0x02`) quantization axis.
42pub const HURRAY_QUANT_FIELD_PER_CHANNEL_AXIS: HurrayDescriptorField = 0x0002_0200;
43
44/// Per-channel affine (`0x02`) buffer index holding the scale vector.
45pub const HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_BUFFER: HurrayDescriptorField = 0x0002_0201;
46
47/// Per-channel affine (`0x02`) buffer index holding the zero-point vector.
48/// Absent for a symmetric scheme.
49pub const HURRAY_QUANT_FIELD_PER_CHANNEL_ZERO_POINT_BUFFER: HurrayDescriptorField = 0x0002_0202;
50
51/// Per-channel affine (`0x02`) element type tag of the scale vector.
52pub const HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_TYPE: HurrayDescriptorField = 0x0002_0203;
53
54/// Per-block affine (`0x03`) quantization axis.
55pub const HURRAY_QUANT_FIELD_PER_BLOCK_AXIS: HurrayDescriptorField = 0x0002_0300;
56
57/// Per-block affine (`0x03`) elements per quantization block.
58pub const HURRAY_QUANT_FIELD_PER_BLOCK_BLOCK_SIZE: HurrayDescriptorField = 0x0002_0301;
59
60/// Per-block affine (`0x03`) buffer index holding the scale vector.
61pub const HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_BUFFER: HurrayDescriptorField = 0x0002_0302;
62
63/// Per-block affine (`0x03`) buffer index holding the zero-point vector.
64/// Absent for a symmetric scheme.
65pub const HURRAY_QUANT_FIELD_PER_BLOCK_ZERO_POINT_BUFFER: HurrayDescriptorField = 0x0002_0303;
66
67/// Per-block affine (`0x03`) element type tag of the scale vector.
68pub const HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_TYPE: HurrayDescriptorField = 0x0002_0304;
69
70/// NF4 (`0x04`) quantization axis.
71pub const HURRAY_QUANT_FIELD_NF4_AXIS: HurrayDescriptorField = 0x0002_0400;
72
73/// NF4 (`0x04`) elements per quantization block.
74pub const HURRAY_QUANT_FIELD_NF4_BLOCK_SIZE: HurrayDescriptorField = 0x0002_0401;
75
76/// NF4 (`0x04`) buffer index holding the scale vector.
77pub const HURRAY_QUANT_FIELD_NF4_SCALE_BUFFER: HurrayDescriptorField = 0x0002_0402;
78
79/// MXFP (`0x05`) quantization axis.
80pub const HURRAY_QUANT_FIELD_MXFP_AXIS: HurrayDescriptorField = 0x0002_0500;
81
82/// MXFP (`0x05`) elements per quantization block.
83pub const HURRAY_QUANT_FIELD_MXFP_BLOCK_SIZE: HurrayDescriptorField = 0x0002_0501;
84
85/// MXFP (`0x05`) buffer index holding the shared-exponent vector.
86pub const HURRAY_QUANT_FIELD_MXFP_SCALE_BUFFER: HurrayDescriptorField = 0x0002_0502;
87
88// ── Statistics (0x0003) ───────────────────────────────────────────────────────
89
90/// Raw `computed_mask` bitfield. Always present when the section is.
91pub const HURRAY_STATS_FIELD_COMPUTED_MASK: HurrayDescriptorField = 0x0003_0000;
92
93/// Non-zero element count. Guarded by `NNZ_VALID` (bit 0).
94pub const HURRAY_STATS_FIELD_NNZ: HurrayDescriptorField = 0x0003_0001;
95
96/// Fraction of elements that are zero. Real scalar, guarded by `SPARSITY_VALID` (bit 1).
97pub const HURRAY_STATS_FIELD_SPARSITY_RATIO: HurrayDescriptorField = 0x0003_0002;
98
99/// Smallest stored value. Real scalar, guarded by `VALUE_RANGE_VALID` (bit 2).
100pub const HURRAY_STATS_FIELD_VALUE_MIN: HurrayDescriptorField = 0x0003_0003;
101
102/// Largest stored value. Real scalar, guarded by `VALUE_RANGE_VALID` (bit 2).
103pub const HURRAY_STATS_FIELD_VALUE_MAX: HurrayDescriptorField = 0x0003_0004;
104
105/// Largest absolute stored value. Real scalar, guarded by `VALUE_RANGE_VALID` (bit 2).
106pub const HURRAY_STATS_FIELD_VALUE_ABS_MAX: HurrayDescriptorField = 0x0003_0005;
107
108/// Arithmetic mean. Real scalar, guarded by `VALUE_STATS_VALID` (bit 3).
109pub const HURRAY_STATS_FIELD_VALUE_MEAN: HurrayDescriptorField = 0x0003_0006;
110
111/// Standard deviation. Real scalar, guarded by `VALUE_STATS_VALID` (bit 3).
112pub const HURRAY_STATS_FIELD_VALUE_STDDEV: HurrayDescriptorField = 0x0003_0007;
113
114/// `N` of N:M structured sparsity. Guarded by `NM_SPARSITY_VALID` (bit 4).
115pub const HURRAY_STATS_FIELD_NM_N: HurrayDescriptorField = 0x0003_0008;
116
117/// `M` of N:M structured sparsity. Guarded by `NM_SPARSITY_VALID` (bit 4).
118pub const HURRAY_STATS_FIELD_NM_M: HurrayDescriptorField = 0x0003_0009;
119
120/// Whether any element is NaN. `0` or `1`, guarded by `NAN_INF_VALID` (bit 5).
121pub const HURRAY_STATS_FIELD_HAS_NAN: HurrayDescriptorField = 0x0003_000A;
122
123/// Whether any element is infinite. `0` or `1`, guarded by `NAN_INF_VALID` (bit 5).
124pub const HURRAY_STATS_FIELD_HAS_INF: HurrayDescriptorField = 0x0003_000B;
125
126// ── Shard (0x0004) ────────────────────────────────────────────────────────────
127
128/// Shape of the logical parent tensor. Unsigned array, length equal to the rank.
129pub const HURRAY_SHARD_FIELD_PARENT_SHAPE: HurrayDescriptorField = 0x0004_0000;
130
131/// This shard's starting index within the parent. Unsigned array, length equal
132/// to the rank.
133pub const HURRAY_SHARD_FIELD_SHARD_OFFSET: HurrayDescriptorField = 0x0004_0001;
134
135// ── Extension type (0x0005) ───────────────────────────────────────────────────
136
137/// Width of one element in bits.
138pub const HURRAY_EXT_TYPE_FIELD_BIT_WIDTH: HurrayDescriptorField = 0x0005_0000;
139
140/// Elements packed per storage byte; `1` when unpacked.
141pub const HURRAY_EXT_TYPE_FIELD_PACKING_FACTOR: HurrayDescriptorField = 0x0005_0001;
142
143/// Whether the type is floating-point. `0` or `1`.
144pub const HURRAY_EXT_TYPE_FIELD_IS_FLOAT: HurrayDescriptorField = 0x0005_0002;
145
146/// Whether the type is signed. `0` or `1`.
147pub const HURRAY_EXT_TYPE_FIELD_IS_SIGNED: HurrayDescriptorField = 0x0005_0003;
148
149/// Number of sign bits.
150pub const HURRAY_EXT_TYPE_FIELD_SIGN_BITS: HurrayDescriptorField = 0x0005_0004;
151
152/// Number of exponent bits; `0` for integer types.
153pub const HURRAY_EXT_TYPE_FIELD_EXPONENT_BITS: HurrayDescriptorField = 0x0005_0005;
154
155/// Number of mantissa bits.
156pub const HURRAY_EXT_TYPE_FIELD_MANTISSA_BITS: HurrayDescriptorField = 0x0005_0006;
157
158/// Exponent bias; `0` for integer types.
159pub const HURRAY_EXT_TYPE_FIELD_EXPONENT_BIAS: HurrayDescriptorField = 0x0005_0007;
160
161/// Whether the type encodes NaN. `0` or `1`.
162pub const HURRAY_EXT_TYPE_FIELD_HAS_NAN: HurrayDescriptorField = 0x0005_0008;
163
164/// Whether the type encodes infinity. `0` or `1`.
165pub const HURRAY_EXT_TYPE_FIELD_HAS_INF: HurrayDescriptorField = 0x0005_0009;
166
167// ── Composite member (0x0006) ─────────────────────────────────────────────────
168
169/// This tensor's role within its enclosing composite: correction `0x00`,
170/// base `0x01`.
171pub const HURRAY_COMPOSITE_MEMBER_FIELD_ROLE: HurrayDescriptorField = 0x0006_0000;
172
173// ── Internal resolution ───────────────────────────────────────────────────────
174
175/// Rejects a non-zero `level`.
176///
177/// Nesting is a layout concern; no section nests. Silently ignoring `level` here
178/// would let a caller believe it had read a nested level that cannot exist.
179fn check_level(level: u32) -> Result<(), HurrayStatus> {
180    if level != 0 {
181        return Err(HURRAY_ERR_INDEX_OUT_OF_BOUNDS);
182    }
183    Ok(())
184}
185
186/// Decodes the quantization section, or reports its absence.
187///
188/// Decoded per call rather than cached in the handle: `hurray-core` stores the
189/// section verbatim because typed decode belongs to a layer with schema
190/// context, so caching here would move a possible failure into
191/// `hurray_descriptor_decode`, which today accepts a descriptor whose
192/// quantization bytes it never typed. The payload is at most 24 bytes of
193/// fixed-width fields, so the decode is arithmetic, not allocation.
194fn quantization(desc: &TensorDescriptor) -> Result<QuantizationDescriptor, HurrayStatus> {
195    let bytes = desc
196        .quantization
197        .as_deref()
198        .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT)?;
199    QuantizationDescriptor::decode(bytes)
200        .map(|(q, _)| q)
201        .map_err(|e| status_from_core_error(&e))
202}
203
204/// Borrows the statistics section, or reports its absence.
205fn statistics(desc: &TensorDescriptor) -> Result<&Statistics, HurrayStatus> {
206    desc.statistics.as_ref().ok_or(HURRAY_ERR_FIELD_NOT_PRESENT)
207}
208
209/// Borrows the shard section, or reports its absence.
210fn shard(desc: &TensorDescriptor) -> Result<&ShardDescriptor, HurrayStatus> {
211    desc.shard.as_ref().ok_or(HURRAY_ERR_FIELD_NOT_PRESENT)
212}
213
214/// Borrows the extension type section, or reports its absence.
215fn ext_type(desc: &TensorDescriptor) -> Result<&ExtensionTypeDescriptor, HurrayStatus> {
216    desc.extension_type
217        .as_ref()
218        .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT)
219}
220
221/// Gates a statistic on its `computed_mask` bit.
222///
223/// The spec requires a reader to check the guard bit before using a statistic.
224/// Returning [`HURRAY_ERR_FIELD_NOT_PRESENT`] for a clear bit enforces that
225/// instead of advertising it: a C caller cannot read an uncomputed statistic by
226/// forgetting to test the mask, which is the whole failure mode of an advisory
227/// section whose fields are always physically present.
228fn guarded<T>(valid: bool, value: T) -> Result<T, HurrayStatus> {
229    if valid {
230        Ok(value)
231    } else {
232        Err(HURRAY_ERR_FIELD_NOT_PRESENT)
233    }
234}
235
236/// Resolves an unsigned scalar field against a section.
237pub(super) fn u64_scalar(
238    desc: &TensorDescriptor,
239    field: HurrayDescriptorField,
240    level: u32,
241) -> Result<u64, HurrayStatus> {
242    check_level(level)?;
243
244    match field {
245        // Quantization
246        HURRAY_QUANT_FIELD_SCHEME_TAG => Ok(u64::from(quantization(desc)?.scheme_tag().tag())),
247        HURRAY_QUANT_FIELD_PER_CHANNEL_AXIS
248        | HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_BUFFER
249        | HURRAY_QUANT_FIELD_PER_CHANNEL_ZERO_POINT_BUFFER
250        | HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_TYPE
251        | HURRAY_QUANT_FIELD_PER_BLOCK_AXIS
252        | HURRAY_QUANT_FIELD_PER_BLOCK_BLOCK_SIZE
253        | HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_BUFFER
254        | HURRAY_QUANT_FIELD_PER_BLOCK_ZERO_POINT_BUFFER
255        | HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_TYPE
256        | HURRAY_QUANT_FIELD_NF4_AXIS
257        | HURRAY_QUANT_FIELD_NF4_BLOCK_SIZE
258        | HURRAY_QUANT_FIELD_NF4_SCALE_BUFFER
259        | HURRAY_QUANT_FIELD_MXFP_AXIS
260        | HURRAY_QUANT_FIELD_MXFP_BLOCK_SIZE
261        | HURRAY_QUANT_FIELD_MXFP_SCALE_BUFFER => quant_u64(&quantization(desc)?, field),
262
263        // Statistics
264        HURRAY_STATS_FIELD_COMPUTED_MASK => Ok(u64::from(statistics(desc)?.computed_mask.0)),
265        HURRAY_STATS_FIELD_NNZ => {
266            let s = statistics(desc)?;
267            guarded(s.computed_mask.nnz_valid(), s.nnz)
268        }
269        HURRAY_STATS_FIELD_NM_N => {
270            let s = statistics(desc)?;
271            guarded(s.computed_mask.nm_sparsity_valid(), u64::from(s.nm_n))
272        }
273        HURRAY_STATS_FIELD_NM_M => {
274            let s = statistics(desc)?;
275            guarded(s.computed_mask.nm_sparsity_valid(), u64::from(s.nm_m))
276        }
277        HURRAY_STATS_FIELD_HAS_NAN => {
278            let s = statistics(desc)?;
279            guarded(s.computed_mask.nan_inf_valid(), u64::from(s.has_nan))
280        }
281        HURRAY_STATS_FIELD_HAS_INF => {
282            let s = statistics(desc)?;
283            guarded(s.computed_mask.nan_inf_valid(), u64::from(s.has_inf))
284        }
285
286        // Extension type
287        HURRAY_EXT_TYPE_FIELD_BIT_WIDTH => Ok(u64::from(ext_type(desc)?.bit_width)),
288        HURRAY_EXT_TYPE_FIELD_PACKING_FACTOR => Ok(u64::from(ext_type(desc)?.packing_factor)),
289        HURRAY_EXT_TYPE_FIELD_IS_FLOAT => Ok(u64::from(ext_type(desc)?.is_float)),
290        HURRAY_EXT_TYPE_FIELD_IS_SIGNED => Ok(u64::from(ext_type(desc)?.is_signed)),
291        HURRAY_EXT_TYPE_FIELD_SIGN_BITS => Ok(u64::from(ext_type(desc)?.sign_bits)),
292        HURRAY_EXT_TYPE_FIELD_EXPONENT_BITS => Ok(u64::from(ext_type(desc)?.exponent_bits)),
293        HURRAY_EXT_TYPE_FIELD_MANTISSA_BITS => Ok(u64::from(ext_type(desc)?.mantissa_bits)),
294        HURRAY_EXT_TYPE_FIELD_EXPONENT_BIAS => Ok(u64::from(ext_type(desc)?.exponent_bias)),
295        HURRAY_EXT_TYPE_FIELD_HAS_NAN => Ok(u64::from(ext_type(desc)?.has_nan)),
296        HURRAY_EXT_TYPE_FIELD_HAS_INF => Ok(u64::from(ext_type(desc)?.has_inf)),
297
298        // Composite member
299        HURRAY_COMPOSITE_MEMBER_FIELD_ROLE => desc
300            .composite_member
301            .as_ref()
302            .map(|cm| u64::from(cm.member_role.wire_byte()))
303            .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT),
304
305        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
306    }
307}
308
309/// Resolves a scheme-specific unsigned quantization field.
310///
311/// Split out so the `(field, scheme)` pairing stays one match: the scheme is the
312/// identifier's discriminant byte, so a mismatch falls through to
313/// [`HURRAY_ERR_FIELD_NOT_APPLICABLE`] with no separate tag comparison.
314fn quant_u64(
315    q: &QuantizationDescriptor,
316    field: HurrayDescriptorField,
317) -> Result<u64, HurrayStatus> {
318    match (field, q) {
319        // Per-channel affine
320        (HURRAY_QUANT_FIELD_PER_CHANNEL_AXIS, QuantizationDescriptor::PerChannelAffine(s)) => {
321            Ok(u64::from(s.axis()))
322        }
323        (
324            HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_BUFFER,
325            QuantizationDescriptor::PerChannelAffine(s),
326        ) => Ok(u64::from(s.scale_buffer_index())),
327        (
328            HURRAY_QUANT_FIELD_PER_CHANNEL_ZERO_POINT_BUFFER,
329            QuantizationDescriptor::PerChannelAffine(s),
330        ) => s
331            .zero_point_buffer_index()
332            .map(u64::from)
333            .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT),
334        (
335            HURRAY_QUANT_FIELD_PER_CHANNEL_SCALE_TYPE,
336            QuantizationDescriptor::PerChannelAffine(s),
337        ) => Ok(u64::from(s.scale_type().tag())),
338
339        // Per-block affine
340        (HURRAY_QUANT_FIELD_PER_BLOCK_AXIS, QuantizationDescriptor::PerBlockAffine(s)) => {
341            Ok(u64::from(s.axis()))
342        }
343        (HURRAY_QUANT_FIELD_PER_BLOCK_BLOCK_SIZE, QuantizationDescriptor::PerBlockAffine(s)) => {
344            Ok(u64::from(s.block_size()))
345        }
346        (HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_BUFFER, QuantizationDescriptor::PerBlockAffine(s)) => {
347            Ok(u64::from(s.scale_buffer_index()))
348        }
349        (
350            HURRAY_QUANT_FIELD_PER_BLOCK_ZERO_POINT_BUFFER,
351            QuantizationDescriptor::PerBlockAffine(s),
352        ) => s
353            .zero_point_buffer_index()
354            .map(u64::from)
355            .ok_or(HURRAY_ERR_FIELD_NOT_PRESENT),
356        (HURRAY_QUANT_FIELD_PER_BLOCK_SCALE_TYPE, QuantizationDescriptor::PerBlockAffine(s)) => {
357            Ok(u64::from(s.scale_type().tag()))
358        }
359
360        // NF4
361        (HURRAY_QUANT_FIELD_NF4_AXIS, QuantizationDescriptor::Nf4(s)) => Ok(u64::from(s.axis())),
362        (HURRAY_QUANT_FIELD_NF4_BLOCK_SIZE, QuantizationDescriptor::Nf4(s)) => {
363            Ok(u64::from(s.block_size()))
364        }
365        (HURRAY_QUANT_FIELD_NF4_SCALE_BUFFER, QuantizationDescriptor::Nf4(s)) => {
366            Ok(u64::from(s.scale_buffer_index()))
367        }
368
369        // MXFP
370        (HURRAY_QUANT_FIELD_MXFP_AXIS, QuantizationDescriptor::Mxfp(s)) => Ok(u64::from(s.axis())),
371        (HURRAY_QUANT_FIELD_MXFP_BLOCK_SIZE, QuantizationDescriptor::Mxfp(s)) => {
372            Ok(u64::from(s.block_size()))
373        }
374        (HURRAY_QUANT_FIELD_MXFP_SCALE_BUFFER, QuantizationDescriptor::Mxfp(s)) => {
375            Ok(u64::from(s.scale_buffer_index()))
376        }
377
378        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
379    }
380}
381
382/// Resolves a signed scalar field against a section.
383pub(super) fn i64_scalar(
384    desc: &TensorDescriptor,
385    field: HurrayDescriptorField,
386    level: u32,
387) -> Result<i64, HurrayStatus> {
388    check_level(level)?;
389
390    match field {
391        HURRAY_QUANT_FIELD_PER_TENSOR_ZERO_POINT => match quantization(desc)? {
392            QuantizationDescriptor::PerTensorAffine(s) => Ok(i64::from(s.zero_point())),
393            _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
394        },
395        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
396    }
397}
398
399/// Resolves a real scalar field against a section.
400pub(super) fn f64_scalar(
401    desc: &TensorDescriptor,
402    field: HurrayDescriptorField,
403    level: u32,
404) -> Result<f64, HurrayStatus> {
405    check_level(level)?;
406
407    match field {
408        HURRAY_QUANT_FIELD_PER_TENSOR_SCALE => match quantization(desc)? {
409            QuantizationDescriptor::PerTensorAffine(s) => Ok(f64::from(s.scale())),
410            _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
411        },
412
413        HURRAY_STATS_FIELD_SPARSITY_RATIO => {
414            let s = statistics(desc)?;
415            guarded(s.computed_mask.sparsity_valid(), s.sparsity_ratio)
416        }
417        HURRAY_STATS_FIELD_VALUE_MIN => {
418            let s = statistics(desc)?;
419            guarded(s.computed_mask.value_range_valid(), s.value_min)
420        }
421        HURRAY_STATS_FIELD_VALUE_MAX => {
422            let s = statistics(desc)?;
423            guarded(s.computed_mask.value_range_valid(), s.value_max)
424        }
425        HURRAY_STATS_FIELD_VALUE_ABS_MAX => {
426            let s = statistics(desc)?;
427            guarded(s.computed_mask.value_range_valid(), s.value_abs_max)
428        }
429        HURRAY_STATS_FIELD_VALUE_MEAN => {
430            let s = statistics(desc)?;
431            guarded(s.computed_mask.value_stats_valid(), s.value_mean)
432        }
433        HURRAY_STATS_FIELD_VALUE_STDDEV => {
434            let s = statistics(desc)?;
435            guarded(s.computed_mask.value_stats_valid(), s.value_stddev)
436        }
437
438        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
439    }
440}
441
442/// Resolves an unsigned array field against a section.
443pub(super) fn u64_array<'a>(
444    desc: &'a TensorDescriptor,
445    field: HurrayDescriptorField,
446    level: u32,
447) -> Result<U64Source<'a>, HurrayStatus> {
448    check_level(level)?;
449
450    match field {
451        HURRAY_SHARD_FIELD_PARENT_SHAPE => Ok(U64Source::Direct(&shard(desc)?.parent_shape)),
452        HURRAY_SHARD_FIELD_SHARD_OFFSET => Ok(U64Source::Direct(&shard(desc)?.shard_offset)),
453        _ => Err(HURRAY_ERR_FIELD_NOT_APPLICABLE),
454    }
455}