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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
// SPDX-License-Identifier: MIT OR Apache-2.0
//! FDX-owned stable code tables, magic, version, flags, and sentinels — the
//! **normative source** for every shared dtype/quant/granularity/substrate/
//! gather/extent code (spec §5.2, §6.0, Appendix A). The sibling FKC kernel-
//! contract format references these by symbol and re-numbers nothing; a
//! build-time mapping test (added with the conversion fns in the next slice)
//! is the binding, so a source-enum reorder breaks the build rather than
//! silently shifting the ABI.
//!
//! Field widths are chosen to match the `FDXSidecar` struct fields they
//! populate (added in the sidecar slice): the `0xFFFF` sentinels are `u16`,
//! the `0xFFFF_FFFF` sentinels and `FDXSidecar.flags` are `u32`, scale
//! granularity is `u8`.
// --- magic / schema version (§5.2) ---
/// `"FDX\0"`.
pub const FDX_MAGIC: u32 = 0x4644_5800;
/// FDX **schema** major — independent of the DLPack ABI version.
pub const FDX_VERSION_1: u32 = 1;
pub const FDX_VERSION_MAX: u32 = 1;
// --- sentinels (Appendix A) ---
pub const FDX_SYM_NONE: u32 = 0xFFFF_FFFF;
pub const FDX_SESSION_NONE: u32 = 0;
pub const FDX_DTYPE_NONE: u16 = 0xFFFF;
pub const FDX_BUFFER_INLINE: u32 = 0xFFFF_FFFF;
pub const FDX_BUFFER_NONE: u32 = 0xFFFF_FFFE;
pub const FDX_BLOCK_UNMAPPED: u32 = 0xFFFF_FFFF;
// --- FDXSidecar.flags (§5.2 authoritative bit-allocation table; `flags` is u32) ---
pub const FDX_FLAG_HAS_DTYPE_EXT: u32 = 1 << 0;
pub const FDX_FLAG_HAS_QUANT: u32 = 1 << 1;
pub const FDX_FLAG_HAS_SYMBOLIC: u32 = 1 << 2;
pub const FDX_FLAG_HAS_TILING: u32 = 1 << 3;
pub const FDX_FLAG_IS_BUNDLE: u32 = 1 << 4;
/// Base bytes alone are NOT a usable tensor (quant/sub-byte/unbacked tail) —
/// drives the refuse-or-dequantize producer policy (§9).
pub const FDX_FLAG_MEANING_REQUIRES_EXT: u32 = 1 << 5;
pub const FDX_FLAG_READ_ONLY: u32 = 1 << 6;
/// Base bytes are a physical block pool re-interpreted via a block table
/// (§6.9). Implies [`FDX_FLAG_MEANING_REQUIRES_EXT`] (validator V18).
pub const FDX_FLAG_HAS_GATHER: u32 = 1 << 7;
/// ≥1 extent is `kind = AFFINE` (§6.4). Advisory fast-reject; the per-extent
/// `kind` byte is authoritative.
pub const FDX_FLAG_HAS_AFFINE_EXTENT: u32 = 1 << 8;
// bits 9..=31 reserved (0); the next addition takes bit 9 from this table.
/// Every allocated `FDX_FLAG_*` bit, in allocation order. The single source
/// for the no-collision build-time test; a future flag appends here.
pub const FDX_FLAG_ALL: = ;
/// The **meaning-bearing** flag subset (§3): a set bit here means the base bytes
/// are NOT a self-sufficient standard tensor, so the sidecar MUST also set
/// `FDX_FLAG_MEANING_REQUIRES_EXT`. Single source of truth shared by the V3
/// honesty predicate and the meaning-bearing ⇒ `MEANING_REQUIRES_EXT` arm
/// (`check_v22_meaning_bearing_implies_ext`); a future meaning-bearing flag appends
/// here and both the honesty check and the implication follow for free.
/// `MEANING_REQUIRES_EXT` is the *target* of the implication, so it is not listed.
pub const FDX_FLAG_MEANING_BEARING: & = &;
// --- FDXExtent.kind (§6.4) ---
pub const FDX_EXTENT_SCALAR: u16 = 0;
pub const FDX_EXTENT_RANGE: u16 = 1;
pub const FDX_EXTENT_AFFINE: u16 = 2;
/// Affine term-count cap; overflow is a typed error (§6.4).
pub const FDX_AFFINE_MAX_TERMS: usize = 4;
/// `FDXExtent.cap_kind` (affine): explicit capacity (v1).
pub const FDX_CAP_KIND_EXPLICIT: u16 = 0;
/// Reserved for a future capacity-from-affine-max form.
pub const FDX_CAP_KIND_AFFINE_MAX: u16 = 1;
// --- FDXIndexedResidency.kind (gather, §6.9) ---
pub const FDX_GATHER_NONE: u16 = 0;
pub const FDX_GATHER_PAGED_BLOCKS: u16 = 1;
// --- FDXQuant.family (§6.2) — FDX is the normative owner of these codes ---
pub const FDX_QUANT_NONE: u16 = 0xFFFF;
/// Baked INLINE scales; `ggml_dtype` ONLY, never `PerBlock`/separate scale.
pub const FDX_QUANT_GGML_BLOCK: u16 = 0;
/// F8E8M0 per-block scale; the **sole** `PerBlock` user.
pub const FDX_QUANT_MX: u16 = 1;
pub const FDX_QUANT_AFFINE_INT: u16 = 2;
/// Per-tensor/token/channel affine float quant.
pub const FDX_QUANT_AFFINE_FLOAT: u16 = 3;
/// nf4/QLoRA: low-bit data + a SEPARATE block-shaped scale operand (§6.2).
pub const FDX_QUANT_AFFINE_BLOCK: u16 = 4;
// --- FDXScaleGranularity (§6.2) ---
pub const FDX_SCALE_GRAN_PER_TENSOR: u8 = 0;
pub const FDX_SCALE_GRAN_PER_TOKEN: u8 = 1;
pub const FDX_SCALE_GRAN_PER_CHANNEL: u8 = 2;
/// `PerBlock` is MX-family only (§6.2).
pub const FDX_SCALE_GRAN_PER_BLOCK: u8 = 3;
// --- FDXScalePlacement (§6.2) ---
/// Scales interleaved in the data block (GGML family).
pub const FDX_SCALE_PLACEMENT_INLINE: u8 = 0;
/// `scale_buffer` is a real buffer-table index (MX / AFFINE_*).
pub const FDX_SCALE_PLACEMENT_SEPARATE_BUFFER: u8 = 1;
/// Scale tensor shape per granularity (broadcast per axis).
pub const FDX_SCALE_PLACEMENT_BROADCAST_PER_AXIS: u8 = 2;
// --- FDXBufferRef.role (§7.2, §6.9.3) ---
pub const FDX_BUFFER_ROLE_DATA: u8 = 0;
pub const FDX_BUFFER_ROLE_SCALE: u8 = 1;
pub const FDX_BUFFER_ROLE_ZERO_POINT: u8 = 2;
pub const FDX_BUFFER_ROLE_BUNDLE_BACKING: u8 = 3;
pub const FDX_BUFFER_ROLE_AUX: u8 = 4;
/// Gather: the physical block pool (§6.9.3).
pub const FDX_BUFFER_ROLE_POOL: u8 = 5;
/// Gather: the `[num_sequences, max_blocks_per_seq]` block-id table (§6.9.3).
pub const FDX_BUFFER_ROLE_BLOCK_TABLE: u8 = 6;
/// Gather: the `[num_sequences]` per-sequence live-length buffer (§6.9.3).
pub const FDX_BUFFER_ROLE_CONTEXT_LENS: u8 = 7;
// --- FDXResidency.tier (§6.6) — three-tier residency ---
pub const FDX_TIER_DEVICE: u8 = 0;
pub const FDX_TIER_HOST: u8 = 1;
pub const FDX_TIER_DISK_MMAP: u8 = 2;
// --- FDXResidency.substrate (§6.0/§6.6) — FDX-owned; pins `SubstrateClass`
// (that source enum is `#[non_exhaustive]`; these codes are NOT its
// discriminants — the §6.0 conversion fn + build-time test is the binding). ---
pub const FDX_SUBSTRATE_HOST_BYTES: u8 = 0;
pub const FDX_SUBSTRATE_CUDA_UNTYPED: u8 = 1;
pub const FDX_SUBSTRATE_VULKAN_BUFFER: u8 = 2;
pub const FDX_SUBSTRATE_METAL_BUFFER: u8 = 3;
// --- FDXResidency.backend_id (§6.0/§6.6) — FDX-owned; pins `BackendId`
// (`Aocl`/`Mkl` already retired from that enum). NOT a `BackendId`
// discriminant; the §6.0 conversion fn + build-time test is the binding. ---
pub const FDX_BACKEND_CPU: u8 = 0;
pub const FDX_BACKEND_CUDA: u8 = 1;
pub const FDX_BACKEND_VULKAN: u8 = 2;
pub const FDX_BACKEND_METAL: u8 = 3;
// --- FDXStorage.class (§6.7) ---
pub const FDX_STORAGE_SHARED: u8 = 0;
pub const FDX_STORAGE_SESSION: u8 = 1;
pub const FDX_STORAGE_TRANSIENT: u8 = 2;
// --- FDX ggml_dtype codes (§6.2) — FDX-owned; mirror `GgmlDType::to_u32`.
// Re-declared here so the conversion fns + mapping test reference FDX symbols,
// not the source enum's `to_u32` (which the §6.0 binding keeps pinned). ---
pub const FDX_GGML_F32: u16 = 0;
pub const FDX_GGML_F16: u16 = 1;
pub const FDX_GGML_Q4_0: u16 = 2;
pub const FDX_GGML_Q4_1: u16 = 3;
pub const FDX_GGML_Q5_0: u16 = 6;
pub const FDX_GGML_Q5_1: u16 = 7;
pub const FDX_GGML_Q8_0: u16 = 8;
pub const FDX_GGML_Q8_1: u16 = 9;
pub const FDX_GGML_Q2K: u16 = 10;
pub const FDX_GGML_Q3K: u16 = 11;
pub const FDX_GGML_Q4K: u16 = 12;
pub const FDX_GGML_Q5K: u16 = 13;
pub const FDX_GGML_Q6K: u16 = 14;
pub const FDX_GGML_Q8K: u16 = 15;
pub const FDX_GGML_IQ4_NL: u16 = 20;
pub const FDX_GGML_IQ4_XS: u16 = 23;
pub const FDX_GGML_IQ2_XXS: u16 = 16;
pub const FDX_GGML_IQ2_XS: u16 = 17;
pub const FDX_GGML_IQ3_XXS: u16 = 18;
pub const FDX_GGML_IQ1_S: u16 = 19;
pub const FDX_GGML_IQ3_S: u16 = 21;
pub const FDX_GGML_IQ2_S: u16 = 22;
pub const FDX_GGML_IQ1_M: u16 = 29;
pub const FDX_GGML_TQ1_0: u16 = 34;
pub const FDX_GGML_TQ2_0: u16 = 35;
pub const FDX_GGML_MXFP4: u16 = 39;
pub const FDX_GGML_NVFP4: u16 = 40;
pub const FDX_GGML_BF16: u16 = 30;
// --- FDX logical dtype codes (§6.1 table) — the subset the validators name.
// FDX-owned stable table; values match the §6.1 declaration order. ---
pub const FDX_DTYPE_U8: u16 = 0;
pub const FDX_DTYPE_I8: u16 = 1;
pub const FDX_DTYPE_U32: u16 = 2;
pub const FDX_DTYPE_I16: u16 = 3;
pub const FDX_DTYPE_I32: u16 = 4;
pub const FDX_DTYPE_I64: u16 = 5;
pub const FDX_DTYPE_BF16: u16 = 6;
pub const FDX_DTYPE_F16: u16 = 7;
pub const FDX_DTYPE_F32: u16 = 8;
pub const FDX_DTYPE_F64: u16 = 9;
pub const FDX_DTYPE_F8E4M3: u16 = 10;
pub const FDX_DTYPE_F6E2M3: u16 = 11;
pub const FDX_DTYPE_F6E3M2: u16 = 12;
pub const FDX_DTYPE_F4: u16 = 13;
pub const FDX_DTYPE_F8E8M0: u16 = 14;
// --- Low-bit logical codes with NO Fuel `DType` (the 0x01xx family). These name
// sub-byte element types a producer/consumer (e.g. Baracuda) carries through the
// sidecar when the base is the opaque `uint8` stand-in; Fuel does not process
// them internally, so `fdx_to_dtype` returns `None` for them (like the
// `GENERIC_LOW_BIT_*` escapes). Added 2026-06-19 per the Baracuda dtype
// reconciliation (packed S4/U4 two-per-byte; bitpacked Bin). ---
/// Packed 4-bit SIGNED integer (two per byte; DENSE_SUBBYTE, `bit_width = 4`).
pub const FDX_DTYPE_I4: u16 = 0x0102;
/// Packed 4-bit UNSIGNED integer (two per byte; DENSE_SUBBYTE, `bit_width = 4`).
pub const FDX_DTYPE_U4: u16 = 0x0103;
/// Bitpacked binary (eight per byte; DENSE_SUBBYTE, `bit_width = 1`). No standard
/// DLPack representation — the meaning rides the sidecar.
pub const FDX_DTYPE_B1: u16 = 0x0104;
// --- Base-riding RESERVED logical codes (the 0x02xx family). UNLIKE the 0x01xx
// codes above, these name element types the BASE DLPack `DLDataType` CAN express
// faithfully (`kDLComplex`, `kDLBool`), so per §6.1.1 a plain tensor rides the
// base and emits NO `FDXDTypeExt` at all. The code is "kept for completeness":
// it is the namespace slot to fill in a `FDXBufferRef.dtype` / `FDXQuant` /
// `FDXDTypeExt.logical_dtype` field ONLY when a sidecar already exists for some
// OTHER reason (multi-buffer / quant / residency / symbolic). It is therefore
// deliberately one-way: `fdx_to_dtype` returns `None` for it, because the
// authoritative element type lives in the base, not in this placeholder. ---
/// Complex, 2×f32 (reserved base-riding placeholder — base is `kDLComplex`).
/// No Fuel `DType` today; the row exists for the namespace-field case above.
pub const FDX_DTYPE_COMPLEX64: u16 = 0x0200;
/// Boolean (reserved base-riding placeholder — base is `kDLBool`). `DType::Bool`
/// rides the base (§6.1.1); this code is only ever written into a namespace
/// field when a sidecar exists for another reason, never as a standalone
/// `FDXDTypeExt`.
pub const FDX_DTYPE_BOOL: u16 = 0x0201;
// --- FDXPacking codes (§6.1 packing table) — the value written into
// `FDXDTypeExt.packing`. The COMPLETE set the spec defines; exported here so
// consumers name them rather than mirroring the table locally (a partial local
// copy already diverged once — GAP-248). `FDXPacking` is the sole packing
// authority (§3.4); the native DLPack `IS_SUBBYTE_TYPE_PADDED` flag is unused. ---
/// One logical element per `ceil(bit_width/8)` bytes (e.g. F8E4M3, F8E8M0).
pub const FDX_PACKING_BYTE_ALIGNED: u8 = 0;
/// Sub-byte elements packed back-to-back, no per-block framing (e.g. 2×F4/byte).
pub const FDX_PACKING_DENSE_SUBBYTE: u8 = 1;
/// OCP-microscaling: a packed sub-byte payload block + a separate F8E8M0 scale
/// per block (block geometry in `FDXQuant`, §6.2).
pub const FDX_PACKING_MX_BLOCK: u8 = 2;
/// ggml/GGUF block layout: scales/mins/quants interleaved in one block struct
/// (per-format byte layout in `FDXQuant`, §6.2).
pub const FDX_PACKING_GGML_BLOCK: u8 = 3;