code wiki / _hdl_build / nx_record_tsv_gate.nx

nx_record_tsv_gate.nx source

↩ module page · 150 lines · 6513 B

1// nx_record_tsv_gate.nx -- referee for the TSV <-> NXR1 compatibility bridge (seq1326 rung 2). 2// 3// T1 IS THE TOOTH THAT MAKES ADOPTION SAFE: a real tab-delimited line survives tsv -> NXR1 -> tsv 4// BYTE-IDENTICAL. Without that, migrating a plane's physical format silently rewrites its data and every 5// legacy reader is a liar. With it, a plane can be stored as NXR1 today and its existing decoders keep 6// reading the exact same bytes (rule 19) until each is migrated deliberately. 7// 8// T5 IS THE TOOTH THAT KEEPS THE BRIDGE HONEST: a record holding a value TSV cannot represent must be 9// REFUSED at render time, not silently emitted as extra columns. T6 is its non-vacuity partner -- the same 10// record with the offending byte removed MUST render fine, proving T5 refuses because of the TAB and not 11// because rendering is simply broken. 12// 13// license_tier: ORIGINAL expect_exit: 0 14import "nx_gate.nx" 15import "nx_record_tsv.nx" 16 17const RG_TEETH: i64 = 8 18const RG_BUF: i64 = 4096 19const RG_A: i64 = 97 20const RG_B: i64 = 98 21const RG_C: i64 = 99 22const RG_X: i64 = 120 23const RG_Y: i64 = 121 24const RG_Z: i64 = 122 25const RG_D4: i64 = 52 26const RG_D2: i64 = 50 27const RG_TAB9: i64 = 9 28const RG_VAL42: i64 = 42 29const RG_DEF: i64 = 0 - 7 30const RG_TINYCAP: i64 = 2 31 32func rg_row(name: *u8, ok: i64) -> i64 { 33 gw(" " as *u8); gw(name) 34 if ok == 1 { gw(" PASS\n" as *u8) } else { gw(" FAIL\n" as *u8) } 35 return 0 36} 37func rg_same(a: *u8, b: *u8, n: i64) -> i64 { 38 var i: i64 = 0 39 var ok: i64 = 1 40 while i < n { if a[i] != b[i] { ok = 0; i = n } else { i = i + 1 } } 41 return ok 42} 43 44func main() -> i64 { 45 let rec: *u8 = sys_mmap(RG_BUF) 46 let out: *u8 = sys_mmap(RG_BUF) 47 let line: *u8 = sys_mmap(RG_BUF) 48 let ty: *u8 = sys_mmap(16) 49 ty[0] = NXR_T_STR as u8 50 ty[1] = NXR_T_I64 as u8 51 ty[2] = NXR_T_STR as u8 52 53 // ---- T1: "abc<TAB>42<TAB>xyz" survives tsv -> NXR1 -> tsv BYTE-IDENTICAL, with the middle column 54 // stored as a REAL i64 in between (not as text passed through untouched). 55 line[0] = RG_A as u8; line[1] = RG_B as u8; line[2] = RG_C as u8 56 line[3] = RG_TAB9 as u8 57 line[4] = RG_D4 as u8; line[5] = RG_D2 as u8 58 line[6] = RG_TAB9 as u8 59 line[7] = RG_X as u8; line[8] = RG_Y as u8; line[9] = RG_Z as u8 60 let rn: i64 = rtv_to_nxr(line, 10, ty, 3, rec) 61 let on: i64 = rtv_to_tsv(rec, rn, 3, out, RG_BUF) 62 var t1: i64 = 0 63 if on == 10 { if rg_same(line, out, 10) == 1 { t1 = 1 } } 64 65 // ---- T2: the middle column really is a TYPED i64, readable by field id without any text parsing. 66 var t2: i64 = 0 67 if nxr_get_i64(rec, rn, 2, RG_DEF) == RG_VAL42 { t2 = 1 } 68 69 // ---- T3: an EMPTY MIDDLE column round-trips ("a<TAB><TAB>c"). 70 line[0] = RG_A as u8; line[1] = RG_TAB9 as u8; line[2] = RG_TAB9 as u8; line[3] = RG_C as u8 71 let rn3: i64 = rtv_to_nxr(line, 4, ty, 0, rec) 72 let on3: i64 = rtv_to_tsv(rec, rn3, 3, out, RG_BUF) 73 var t3: i64 = 0 74 if on3 == 4 { if rg_same(line, out, 4) == 1 { t3 = 1 } } 75 76 // ---- T4: a TRAILING EMPTY column round-trips ("a<TAB>b<TAB>") -- the classic off-by-one every 77 // hand-rolled TSV splitter gets wrong by dropping the final empty field. 78 line[0] = RG_A as u8; line[1] = RG_TAB9 as u8; line[2] = RG_B as u8; line[3] = RG_TAB9 as u8 79 let rn4: i64 = rtv_to_nxr(line, 4, ty, 0, rec) 80 var t4: i64 = 0 81 if nxr_count(rec) == 3 { 82 let on4: i64 = rtv_to_tsv(rec, rn4, 3, out, RG_BUF) 83 if on4 == 4 { if rg_same(line, out, 4) == 1 { t4 = 1 } } 84 } 85 86 // ---- T5 REFUSAL: a stored value containing a TAB cannot be rendered as TSV. Must return the error 87 // code, NOT a line that would parse as two columns. 88 let dirty: *u8 = sys_mmap(64) 89 dirty[0] = RG_A as u8; dirty[1] = RG_TAB9 as u8; dirty[2] = RG_B as u8 90 let d: *u8 = sys_mmap(RG_BUF) 91 var od: i64 = nxr_init(d) 92 od = nxr_add(d, od, 1, NXR_T_STR, dirty, 3) 93 var t5: i64 = 0 94 if rtv_to_tsv(d, od, 1, out, RG_BUF) == RTV_ERR_TAB_IN_VALUE { t5 = 1 } 95 96 // ---- T6 NON-VACUITY for T5: the SAME shape without the tab renders fine. If this failed, T5 would 97 // be passing because rendering is broken, not because the tab was caught. 98 let clean: *u8 = sys_mmap(64) 99 clean[0] = RG_A as u8; clean[1] = RG_C as u8; clean[2] = RG_B as u8 100 let e: *u8 = sys_mmap(RG_BUF) 101 var oe: i64 = nxr_init(e) 102 oe = nxr_add(e, oe, 1, NXR_T_STR, clean, 3) 103 var t6: i64 = 0 104 if rtv_to_tsv(e, oe, 1, out, RG_BUF) == 3 { if rg_same(clean, out, 3) == 1 { t6 = 1 } } 105 106 // ---- T7: an ABSENT field renders as an EMPTY column and does NOT shift the columns after it. 107 // Field 2 is never written; field 3 must still land in column 3. 108 let s: *u8 = sys_mmap(RG_BUF) 109 var os: i64 = nxr_init(s) 110 os = nxr_add(s, os, 1, NXR_T_STR, clean, 1) 111 os = nxr_add(s, os, 3, NXR_T_STR, clean, 1) 112 let on7: i64 = rtv_to_tsv(s, os, 3, out, RG_BUF) 113 var t7: i64 = 0 114 if on7 == 4 { 115 if out[0] == (RG_A as u8) { if out[1] == (RG_TAB9 as u8) { 116 if out[2] == (RG_TAB9 as u8) { if out[3] == (RG_A as u8) { t7 = 1 } } } } 117 } 118 119 // ---- T8: a render that would overflow the caller buffer is REFUSED, never truncated. 120 var t8: i64 = 0 121 if rtv_to_tsv(rec, rn4, 3, out, RG_TINYCAP) == RTV_ERR_CAP { t8 = 1 } 122 123 var passes: i64 = 0 124 if t1 == 1 { passes = passes + 1 } 125 if t2 == 1 { passes = passes + 1 } 126 if t3 == 1 { passes = passes + 1 } 127 if t4 == 1 { passes = passes + 1 } 128 if t5 == 1 { passes = passes + 1 } 129 if t6 == 1 { passes = passes + 1 } 130 if t7 == 1 { passes = passes + 1 } 131 if t8 == 1 { passes = passes + 1 } 132 var green: i64 = 0 133 if passes == RG_TEETH { green = 1 } 134 135 gw("=== nx_record_tsv_gate -- TSV<->NXR1 compatibility bridge (seq1326 rung 2) ===\n" as *u8) 136 rg_row("T1-tsv-nxr-tsv-BYTE-IDENTICAL " as *u8, t1) 137 rg_row("T2-middle-column-is-a-REAL-i64 " as *u8, t2) 138 rg_row("T3-empty-middle-column-round-trips " as *u8, t3) 139 rg_row("T4-trailing-empty-column-round-trips " as *u8, t4) 140 rg_row("T5-REFUSES-to-render-TAB-in-value " as *u8, t5) 141 rg_row("T6-NONVACUITY-same-shape-renders-ok " as *u8, t6) 142 rg_row("T7-absent-field-does-NOT-shift-cols " as *u8, t7) 143 rg_row("T8-overflow-REFUSED-never-truncated " as *u8, t8) 144 gw("verdict=" as *u8) 145 if green == 1 { gw("GREEN" as *u8) } else { gw("RED" as *u8) } 146 gw(" passes=" as *u8); gn(passes); gw("/" as *u8); gn(RG_TEETH); gw("\n" as *u8) 147 148 if green == 1 { return 0 } 149 return 1 150}