code wiki / (root) / nx_hexdump.nx

nx_hexdump.nx source

↩ module page · 137 lines · 4418 B

1// hexdump.nx -- xxd-style byte buffer dump. 2// 3// Produces human-readable byte listings like: 4// 00000000: 4865 6c6c 6f2c 2057 6f72 6c64 210a Hello, World!. 5// 0000000d: 4e69 7368 690a Nishi. 6// 7// Used for: debugging crypto outputs, network packet dumps, IR 8// inspection, anything where hex + ASCII side-by-side is the 9// right debug lens. 10// 11// Format (xxd default): 12// <8-hex offset>: <8 pairs of 2-hex bytes, space between pairs> <ASCII> 13// Bytes 0x20..0x7E render as themselves; others as '.'. 14// 16 bytes per row. 15// 16// Invariants: 17// HD1 Output is deterministic: same input bytes -> same output. 18// HD2 ASCII column padded so rows align visually -- last row 19// with <16 bytes left gets padding spaces. 20// HD3 Offsets are 8 hex digits (fits up to 4 GiB; enough for 21// every realistic buffer). 22 23// nx_safety_envelope: 24// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 25// sil_target: SIL1 26// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 27// verdict: NOT_YET_EVALUATED 28// 29// nx_capability_manifest: 30// variant_class: hex_dump_formatter 31// variant_id: hex_dump_xxd_v1 32// requires_isa: [rv64imac, x86_64] 33// requires_syscalls: [write] 34// requires_ram_min_b: 256 35// tier_floor: NX_TIER_MCU 36// tier_ceiling: NX_TIER_HPC 37// cost_model: 38// flops_per_n: 4.0 // ~4 ops per byte (hex char + sep) 39// bytes_per_n: 4.0 // 2 hex chars + space + ascii char per input byte 40// syscalls_per_n: 0.0625 // 1 write per 16-byte row 41// adversary_class: THREAT_OPPORTUNISTIC 42 43import "nx_syscalls.nx" 44 45// Lowercase hex encode single byte to out[pos..pos+2]. 46func hd_emit_hex_byte(out: *u8, pos: i64, b: i64) -> i64 { 47 let hi: i64 = (b >> 4) & 0xF 48 let lo: i64 = b & 0xF 49 var hc: i64 = 0x30 + hi 50 if hi > 9 { hc = 0x61 + hi - 10 } 51 var lc: i64 = 0x30 + lo 52 if lo > 9 { lc = 0x61 + lo - 10 } 53 out[pos] = hc 54 out[pos + 1] = lc 55 return 2 56} 57 58// 8-hex-digit offset. 59func hd_emit_offset(out: *u8, pos: i64, off: i64) -> i64 { 60 var i: i64 = 7 61 var v: i64 = off 62 while i >= 0 { 63 let nib: i64 = v & 0xF 64 var c: i64 = 0x30 + nib 65 if nib > 9 { c = 0x61 + nib - 10 } 66 out[pos + i] = c 67 v = (v >> 4) & 0x0FFFFFFFFFFFFFFF 68 i = i - 1 69 } 70 return 8 71} 72 73// Dump `n` bytes from `data` into `out`, xxd-style. Returns 74// number of bytes written. 75func hexdump(data: *u8, n: i64, out: *u8) -> i64 { 76 var op: i64 = 0 77 var off: i64 = 0 78 while off < n { 79 // Offset + ": ". 80 op = op + hd_emit_offset(out, op, off) 81 out[op] = 0x3A; op = op + 1 82 out[op] = 0x20; op = op + 1 83 84 // 16 bytes; pairs separated by spaces. Bytes 0..7, space, 85 // 8..15 (standard xxd layout uses one space per pair). 86 let row_end: i64 = off + 16 87 var i: i64 = 0 88 while i < 16 { 89 if off + i < n { 90 op = op + hd_emit_hex_byte(out, op, data[off + i]) 91 } else { 92 // Padding blanks for alignment. 93 out[op] = 0x20; op = op + 1 94 out[op] = 0x20; op = op + 1 95 } 96 if (i & 1) == 1 { 97 out[op] = 0x20; op = op + 1 98 } 99 i = i + 1 100 } 101 102 // ASCII column: 2 extra spaces before. 103 out[op] = 0x20; op = op + 1 104 i = 0 105 while i < 16 { 106 if off + i < n { 107 let b: i64 = data[off + i] 108 if b < 0x20 { out[op] = 0x2E } 109 else { 110 if b > 0x7E { out[op] = 0x2E } 111 else { out[op] = b } 112 } 113 op = op + 1 114 } else { 115 out[op] = 0x20; op = op + 1 116 } 117 i = i + 1 118 } 119 out[op] = 0x0A; op = op + 1 120 121 off = off + 16 122 } 123 return op 124} 125 126// Compile-only smoke: dump "Hello, World!\n" (14 bytes). 127func main() -> i64 { 128 let data: *u8 = "Hello, World!\n" 129 let out: *u8 = sys_mmap(256) 130 let n: i64 = hexdump(data, 14, out) 131 // Should produce exactly one row: "00000000: ..." + newline. 132 if n == 0 { return 1 } 133 if out[0] != 0x30 { return 2 } // '0' 134 if out[8] != 0x3A { return 3 } // ':' 135 if out[10] != 0x34 { return 4 } // '4' of "48" ('H' = 0x48) 136 return 0 137}