nx_le.nx source
↩ module page · 246 lines · 7576 B
1// nx_le.nx -- canonical little-endian / big-endian fixed-width
2// binary read + write primitives.
3//
4// DRY consolidation per the shared-libraries cardinal. Three
5// existing callers inlined their own LE-read helpers:
6//
7// nx_bmp_header.bmp_read_u32 (BMP image parsing)
8// nx_cbor_decode (byte count reads) (CBOR length parsing)
9// nx_wav.nx (WAV audio parsing)
10//
11// Plus the queued GGUF (model weight) + safetensors + ELF / PE
12// header readers. Per the "rule of three" + no-reinventing
13// cardinals: this is the canonical primitive.
14//
15// ===== LE byte order =============================================
16//
17// Little-endian: least-significant byte at lowest address. Used by
18// x86, AArch64 (default), RISC-V, ppc64LE, MIPS-LE, GGUF, ELF on LE
19// platforms, BMP, WAV, safetensors, most binary AI formats.
20//
21// ===== BE byte order =============================================
22//
23// Big-endian: most-significant byte at lowest address. Used by
24// network protocols (TCP/IP headers, DNS, HTTP/2 frames), s390x
25// (big-endian platform), Java class files, PNG, MP3 ID3, MIDI.
26//
27// ===== API =======================================================
28//
29// All readers take (buf: *u8, off: i64) and return the value as i64
30// (sign-extended for signed forms). Caller is responsible for
31// bounds-checking off + width <= buf_len.
32//
33// All writers take (buf: *u8, off: i64, val: i64).
34//
35// Per the bounded-loop cardinal: no loops needed (fixed-width
36// extracts are unrolled).
37//
38// genealogy_id: ietf_rfc_8949_cbor + ieee_754_byte_order +
39// wikipedia_endianness
40// lineage_id: substrate_le_be_v1
41
42// nx_safety_envelope:
43// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
44// sil_target: SIL1
45// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
46// verdict: NOT_YET_EVALUATED
47
48import "nx_syscalls.nx"
49import "nx_tier.nx"
50const NX_MAGIC_32768: i64 = 32768
51const NX_MAGIC_65536: i64 = 65536
52const NX_MAGIC_2147483648: i64 = 2147483648
53const NX_MAGIC_4294967296: i64 = 4294967296
54
55// ===== Sealed-enum: LeVerdict =====================================
56
57const NX_LE_OK: nx_int = 0
58const NX_LE_ERR_OOB: nx_int = 1
59const NX_LE_N_VERDICTS: nx_int = 2
60
61func nx_le_verdict_is_valid(v: nx_int) -> nx_int {
62 if v < 0 { return 0 }
63 if v >= NX_LE_N_VERDICTS { return 0 }
64 return 1
65}
66
67// ===== LE readers ================================================
68
69func nx_le_read_u8(buf: *u8, off: i64) -> i64 {
70 return buf[off]
71}
72
73func nx_le_read_u16(buf: *u8, off: i64) -> i64 {
74 let b0: i64 = buf[off]
75 let b1: i64 = buf[off + 1]
76 return b0 + (b1 << 8)
77}
78
79func nx_le_read_u32(buf: *u8, off: i64) -> i64 {
80 let b0: i64 = buf[off]
81 let b1: i64 = buf[off + 1]
82 let b2: i64 = buf[off + 2]
83 let b3: i64 = buf[off + 3]
84 return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24)
85}
86
87func nx_le_read_u64(buf: *u8, off: i64) -> i64 {
88 let lo: i64 = nx_le_read_u32(buf, off)
89 let hi: i64 = nx_le_read_u32(buf, off + 4)
90 return lo + (hi << 32)
91}
92
93// Signed: extract via the unsigned reader, then sign-extend.
94// For u32 -> i32: if top bit set (>= 0x80000000), subtract 2^32.
95
96func nx_le_read_i16(buf: *u8, off: i64) -> i64 {
97 let u: i64 = nx_le_read_u16(buf, off)
98 if u >= NX_MAGIC_32768 { return u - NX_MAGIC_65536 }
99 return u
100}
101
102func nx_le_read_i32(buf: *u8, off: i64) -> i64 {
103 let u: i64 = nx_le_read_u32(buf, off)
104 if u >= NX_MAGIC_2147483648 { return u - NX_MAGIC_4294967296 }
105 return u
106}
107
108// i64 is the native width -- no sign extension needed (u64 IS i64
109// in the substrate's i64 representation; caller chooses signedness).
110func nx_le_read_i64(buf: *u8, off: i64) -> i64 {
111 return nx_le_read_u64(buf, off)
112}
113
114// ===== LE writers ================================================
115
116func nx_le_write_u8(buf: *u8, off: i64, val: i64) -> i64 {
117 buf[off] = val
118 return 1
119}
120
121func nx_le_write_u16(buf: *u8, off: i64, val: i64) -> i64 {
122 buf[off] = val
123 buf[off + 1] = val >> 8
124 return 2
125}
126
127func nx_le_write_u32(buf: *u8, off: i64, val: i64) -> i64 {
128 buf[off] = val
129 buf[off + 1] = val >> 8
130 buf[off + 2] = val >> 16
131 buf[off + 3] = val >> 24
132 return 4
133}
134
135func nx_le_write_u64(buf: *u8, off: i64, val: i64) -> i64 {
136 nx_le_write_u32(buf, off, val)
137 nx_le_write_u32(buf, off + 4, val >> 32)
138 return 8
139}
140
141// ===== BE readers ================================================
142
143func nx_be_read_u16(buf: *u8, off: i64) -> i64 {
144 let b0: i64 = buf[off]
145 let b1: i64 = buf[off + 1]
146 return (b0 << 8) + b1
147}
148
149func nx_be_read_u32(buf: *u8, off: i64) -> i64 {
150 let b0: i64 = buf[off]
151 let b1: i64 = buf[off + 1]
152 let b2: i64 = buf[off + 2]
153 let b3: i64 = buf[off + 3]
154 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3
155}
156
157func nx_be_read_u64(buf: *u8, off: i64) -> i64 {
158 let hi: i64 = nx_be_read_u32(buf, off)
159 let lo: i64 = nx_be_read_u32(buf, off + 4)
160 return (hi << 32) + lo
161}
162
163// ===== BE writers ================================================
164
165func nx_be_write_u16(buf: *u8, off: i64, val: i64) -> i64 {
166 buf[off] = val >> 8
167 buf[off + 1] = val
168 return 2
169}
170
171func nx_be_write_u32(buf: *u8, off: i64, val: i64) -> i64 {
172 buf[off] = val >> 24
173 buf[off + 1] = val >> 16
174 buf[off + 2] = val >> 8
175 buf[off + 3] = val
176 return 4
177}
178
179func nx_be_write_u64(buf: *u8, off: i64, val: i64) -> i64 {
180 nx_be_write_u32(buf, off, val >> 32)
181 nx_be_write_u32(buf, off + 4, val)
182 return 8
183}
184
185// ===== Self-test ==================================================
186//
187// Closed-form invariants:
188// (a) LE u32 of (0x78 0x56 0x34 0x12) == 0x12345678
189// (b) BE u32 of (0x12 0x34 0x56 0x78) == 0x12345678
190// (c) Round-trip: write_u64(x) then read_u64() = x
191// (d) i32 sign extension: 0xFFFFFFFF -> -1
192// (e) LE / BE u16, u32, u64 all consistent
193
194func main() -> i64 {
195 let buf: *u8 = sys_mmap(64)
196
197 // --- (a) LE u32 ---
198 buf[0] = 0x78; buf[1] = 0x56; buf[2] = 0x34; buf[3] = 0x12
199 let le32: i64 = nx_le_read_u32(buf, 0)
200 if le32 != 0x12345678 { return 10 }
201
202 // --- (b) BE u32 ---
203 buf[4] = 0x12; buf[5] = 0x34; buf[6] = 0x56; buf[7] = 0x78
204 let be32: i64 = nx_be_read_u32(buf, 4)
205 if be32 != 0x12345678 { return 20 }
206
207 // --- (c) Round-trip u64 LE ---
208 nx_le_write_u64(buf, 8, 0x0123456789abcdef)
209 let rt_le: i64 = nx_le_read_u64(buf, 8)
210 if rt_le != 0x0123456789abcdef { return 30 }
211
212 // --- (c) Round-trip u64 BE ---
213 nx_be_write_u64(buf, 16, 0x0123456789abcdef)
214 let rt_be: i64 = nx_be_read_u64(buf, 16)
215 if rt_be != 0x0123456789abcdef { return 31 }
216
217 // --- (d) i32 sign extension ---
218 buf[24] = 0xFF; buf[25] = 0xFF; buf[26] = 0xFF; buf[27] = 0xFF
219 let neg1: i64 = nx_le_read_i32(buf, 24)
220 if neg1 != -1 { return 40 }
221
222 // i16 sign extension on 0xFFFE -> -2
223 buf[28] = 0xFE; buf[29] = 0xFF
224 let neg2: i64 = nx_le_read_i16(buf, 28)
225 if neg2 != -2 { return 41 }
226
227 // --- (e) u16 LE/BE consistency ---
228 buf[30] = 0xAB; buf[31] = 0xCD
229 let le16: i64 = nx_le_read_u16(buf, 30)
230 let be16: i64 = nx_be_read_u16(buf, 30)
231 if le16 != 0xCDAB { return 50 }
232 if be16 != 0xABCD { return 51 }
233
234 // --- (f) u8 round-trip ---
235 nx_le_write_u8(buf, 32, 0x42)
236 if nx_le_read_u8(buf, 32) != 0x42 { return 60 }
237
238 // --- (g) Verdict gate ---
239 var vi: nx_int = 0
240 while vi < NX_LE_N_VERDICTS {
241 if nx_le_verdict_is_valid(vi) != 1 { return 70 + vi }
242 vi = vi + 1
243 }
244
245 return 0
246}