code wiki / _hdl_build / nx_huffcdic_gate.nx
nx_huffcdic_gate.nx source
↩ module page · 106 lines · 7125 B
1// nx_huffcdic_gate.nx -- liar-kill gate for the sovereign HUFF/CDIC decompressor (MOBI compression 17480).
2// Builds a MINIMAL but spec-exact fixture in memory: a HUFF record whose 256 dict1 entries all encode (codelen=1,
3// term, maxcode-raw=1) -> a 1-bit Huffman code where bit '1' selects dictionary phrase 0 and bit '0' selects
4// phrase 1; a CDIC record carrying phrase0="Alice" + phrase1=" " (both terminal); and a 1-byte stream 0x80 =
5// '10000000'. Decoding MUST yield "Alice" + 7 spaces (the '1' then seven '0' bits). Asserts the HUFF table parse
6// (codelen/term/maxcode formula), the CDIC phrase parse (len/flag/bytes), AND the decoded output byte-exact.
7// This proves the core decode plumbing + record formats; the multi-codelen mincode-walk + recursive (non-terminal)
8// phrase paths get a richer encoder-fixture in the next rung. expect_exit: 0 license_tier: ORIGINAL
9import "nx_syscalls.nx"
10import "nx_huffcdic.nx"
11import "nx_gate_verdict.nx"
12
13func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
14func gnum(v0: i64) -> i64 { var v: i64=v0; if v<0 { sys_write(1,"-" as *u8,1); v=0-v } let b: *u8=sys_mmap(24); var k: i64=0; if v==0 {b[0]=48 as u8;k=1} while v>0 {b[k]=(48+(v%10)) as u8; v=v/10; k=k+1} let o: *u8=sys_mmap(24); var j: i64=0; while j<k {o[j]=b[k-1-j];j=j+1} sys_write(1,o,k); return 0 }
15
16func put32(b: *u8, o: i64, v: i64) -> i64 { b[o]=((v>>24)&0xff) as u8; b[o+1]=((v>>16)&0xff) as u8; b[o+2]=((v>>8)&0xff) as u8; b[o+3]=(v&0xff) as u8; return 0 }
17func put16(b: *u8, o: i64, v: i64) -> i64 { b[o]=((v>>8)&0xff) as u8; b[o+1]=(v&0xff) as u8; return 0 }
18
19func main() -> i64 {
20 gp("=== nx_huffcdic_gate: sovereign HUFF/CDIC decompressor (MOBI 17480) -- minimal spec-exact fixture ===\n" as *u8)
21
22 // --- build the HUFF record ---
23 let huff: *u8 = sys_mmap(2048)
24 huff[0]=0x48 as u8; huff[1]=0x55 as u8; huff[2]=0x46 as u8; huff[3]=0x46 as u8
25 huff[4]=0 as u8; huff[5]=0 as u8; huff[6]=0 as u8; huff[7]=0x18 as u8
26 put32(huff, 8, 16) // off1 = 0x10
27 put32(huff, 12, 16 + 256*4) // off2 = 0x410 = 1040
28 var i: i64 = 0
29 while i < 256 { put32(huff, 16 + i*4, 0x181); i = i + 1 } // codelen=1, term=0x80, maxcode-raw=1
30 i = 0
31 while i < 64 { put32(huff, 1040 + i*4, 0); i = i + 1 } // dict2 all zero (term path unused here)
32 let hlen: i64 = 1040 + 64*4
33
34 // --- build the CDIC record (30 bytes) ---
35 let cdic: *u8 = sys_mmap(64)
36 cdic[0]=0x43 as u8; cdic[1]=0x44 as u8; cdic[2]=0x49 as u8; cdic[3]=0x43 as u8
37 cdic[4]=0 as u8; cdic[5]=0 as u8; cdic[6]=0 as u8; cdic[7]=0x10 as u8
38 put32(cdic, 8, 2) // phrases = 2
39 put32(cdic, 12, 1) // bits = 1 -> n = 2
40 put16(cdic, 16, 4) // off[0] = 4 -> phrase0 header at cdic offset 20
41 put16(cdic, 18, 11) // off[1] = 11 -> phrase1 header at cdic offset 27
42 put16(cdic, 20, 0x8005) // blen0 = terminal | len 5
43 cdic[22]=0x41 as u8; cdic[23]=0x6c as u8; cdic[24]=0x69 as u8; cdic[25]=0x63 as u8; cdic[26]=0x65 as u8 // "Alice"
44 put16(cdic, 27, 0x8001) // blen1 = terminal | len 1
45 cdic[29]=0x20 as u8 // " "
46 let clen: i64 = 30
47
48 // --- the compressed stream: 1 byte 0x80 = '1 0000000' ---
49 let data: *u8 = sys_mmap(8); data[0]=0x80 as u8
50
51 // --- load tables ---
52 let d1cl: *i64 = sys_mmap(256*8) as *i64
53 let d1tm: *i64 = sys_mmap(256*8) as *i64
54 let d1mx: *i64 = sys_mmap(256*8) as *i64
55 let mincode: *i64 = sys_mmap(64*8) as *i64
56 let maxcode: *i64 = sys_mmap(64*8) as *i64
57 let dptr: *i64 = sys_mmap(64*8) as *i64
58 let dlen: *i64 = sys_mmap(64*8) as *i64
59 let dflag: *i64 = sys_mmap(64*8) as *i64
60 let dcount: *i64 = sys_mmap(8) as *i64; dcount[0]=0
61
62 let rh: i64 = huff_load(huff, hlen, d1cl, d1tm, d1mx, mincode, maxcode)
63 let rc: i64 = cdic_load(cdic, clen, dptr, dlen, dflag, dcount)
64
65 let out: *u8 = sys_mmap(4096)
66 let ol: i64 = hc_unpack(data, 1, out, 4096, d1cl, d1tm, d1mx, mincode, maxcode, dptr, dlen, dflag, dcount[0])
67
68 gp(" huff_load=" as *u8); gnum(rh); gp(" d1cl[0x80]=" as *u8); gnum(d1cl[0x80]); gp(" d1tm[0x80]=" as *u8); gnum(d1tm[0x80]); gp(" d1mx[0x80]=" as *u8); gnum(d1mx[0x80]); gp("\n" as *u8)
69 gp(" cdic_load=" as *u8); gnum(rc); gp(" dcount=" as *u8); gnum(dcount[0]); gp(" dlen[0]=" as *u8); gnum(dlen[0]); gp(" dflag[0]=" as *u8); gnum(dflag[0]); gp(" dlen[1]=" as *u8); gnum(dlen[1]); gp("\n" as *u8)
70 gp(" decoded len=" as *u8); gnum(ol); gp(" out=\"" as *u8); sys_write(1, out, ol); gp("\"\n" as *u8)
71
72 var pass: i64 = 0; var fail: i64 = 0
73 if rh == 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL huff_load-nonzero\n" as *u8) }
74 if d1cl[0x80] == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL d1cl!=1\n" as *u8) }
75 if d1tm[0x80] != 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL d1tm-not-set\n" as *u8) }
76 if d1mx[0x80] == 0xffffffff { pass=pass+1 } else { fail=fail+1; gp(" FAIL d1mx!=0xffffffff\n" as *u8) }
77 if rc == 0 { pass=pass+1 } else { fail=fail+1; gp(" FAIL cdic_load-nonzero\n" as *u8) }
78 if dcount[0] == 2 { pass=pass+1 } else { fail=fail+1; gp(" FAIL dcount!=2\n" as *u8) }
79 if dlen[0] == 5 { pass=pass+1 } else { fail=fail+1; gp(" FAIL phrase0-len!=5\n" as *u8) }
80 if dflag[0] == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL phrase0-not-terminal\n" as *u8) }
81 if dlen[1] == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL phrase1-len!=1\n" as *u8) }
82 // phrase0 bytes referenced in place == "Alice"
83 let p0: *u8 = dptr[0] as *u8
84 if p0[0]==(0x41 as u8) { if p0[4]==(0x65 as u8) { pass=pass+1 } else { fail=fail+1; gp(" FAIL phrase0-bytes-e\n" as *u8) } } else { fail=fail+1; gp(" FAIL phrase0-bytes-A\n" as *u8) }
85 // decoded output: "Alice" + 7 spaces, len 12
86 if ol == 12 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decoded-len!=12\n" as *u8) }
87 var okA: i64 = 1
88 if out[0]!=(0x41 as u8) { okA=0 }
89 if out[1]!=(0x6c as u8) { okA=0 }
90 if out[2]!=(0x69 as u8) { okA=0 }
91 if out[3]!=(0x63 as u8) { okA=0 }
92 if out[4]!=(0x65 as u8) { okA=0 }
93 if okA == 1 { pass=pass+1 } else { fail=fail+1; gp(" FAIL decoded-prefix!=Alice\n" as *u8) }
94 if ol >= 12 { if out[5]==(0x20 as u8) { if out[11]==(0x20 as u8) { pass=pass+1 } else { fail=fail+1; gp(" FAIL tail-space11\n" as *u8) } } else { fail=fail+1; gp(" FAIL tail-space5\n" as *u8) } } else { fail=fail+1; gp(" FAIL too-short\n" as *u8) }
95
96 gp("HUFFCDIC-GATE pass=" as *u8); gnum(pass); gp(" fail=" as *u8); gnum(fail)
97 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
98 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
99 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
100 let ctr__dry: *i64 = gv_ctr()
101 ctr__dry[0] = pass
102 ctr__dry[1] = pass + fail
103 let rc__dry: i64 = gv_verdict("HUFFCDIC-GATE" as *u8, ctr__dry, "sovereign HUFF/CDIC: HUFF+CDIC record parse + 32-bit Huffman decode -> byte-exact output)" as *u8)
104 sys_exit(rc__dry)
105 return rc__dry
106}