code wiki / (root) / nx_readcap_lib.nx

nx_readcap_lib.nx source

↩ module page · 84 lines · 4187 B

1// nx_readcap_lib.nx -- THE ONE read-into-a-caller's-cap helper (dataio DI16, first cause, 2026-09-06). 2// 3// MEASURED before this lib existed: the io-envelope census worklist held 1,082 silent readers in 803 files, and its 4// SHAPES table showed the top of the population was ONE helper family copied by hand -- `sys_read(fd, buf+n, cap-n)` 5// in a loop that stops when the cap fills and never says so (x28, x22, x20, x19, x15, x13 ...). Every copy is a 6// silent-truncation cap: the caller cannot tell "the file was exactly cap bytes" from "the cap filled and the tail 7// is gone". This lib is the bus stop: ONE loop, ONE named state per outcome, so a consumer that adopts it has no 8// sys_read( site of its own and the census counts it CONVERTED. 9// 10// States (rc_fill): RC_EOF the source ended before the cap (buf holds all of it) / RC_CAPPED the cap filled and the 11// source was NOT probed further (a socket must not be probed: the next byte may never come) / RC_ERR a read failed 12// (st[1] = the rc). rc_read_file_into adds the file-only refinement: after a CAPPED fill it reads ONE more byte, so 13// RC_FULL means "TRUNCATED, more remains" and RC_EXACT means "the file was exactly cap bytes" -- the distinction the 14// hand-rolled loops could never make. rc_state_name spells the TRUNCATED state so any consumer that prints it 15// announces its envelope in the census's own vocabulary. 16// 17// Whole-file reads with no cap at all belong to sys_read_file (nx_syscalls), which sizes from the file; this lib is 18// for the case where the BUFFER is the caller's and the cap is real (a fixed header, a bounded request line, a window). 19// license_tier: ORIGINAL No hw writes (Rule 26). 20import "nx_syscalls.nx" 21 22const RC_EOF: i64 = 0 23const RC_CAPPED: i64 = 1 24const RC_FULL: i64 = 2 25const RC_EXACT: i64 = 3 26const RC_ERR: i64 = 4 27const RC_PROBE_BYTES: i64 = 1 // one byte decides EXACT vs FULL; a bigger probe would only cost more and prove no more 28 29// fill buf[0..cap) from fd until EOF or the cap. Returns bytes read (>= 0). st[0] = RC_EOF | RC_CAPPED | RC_ERR; 30// st[1] = the failing read's rc, else 0. Never reads past cap, never probes: safe on sockets and pipes. 31func rc_fill(fd: i64, buf: *u8, cap: i64, st: *i64) -> i64 { 32 var got: i64 = 0 33 st[0] = RC_EOF 34 st[1] = 0 35 var go: i64 = 1 36 while go == 1 { 37 if got >= cap { go = 0 } else { 38 let r: i64 = sys_read(fd, ((buf as i64) + got) as *u8, cap - got) 39 if r < 0 { st[0] = RC_ERR; st[1] = r; return got } 40 if r == 0 { go = 0 } else { got = got + r } 41 } 42 } 43 if got >= cap { st[0] = RC_CAPPED } 44 return got 45} 46 47// the file-only refinement: a CAPPED fill is followed by ONE probe read, so the caller learns whether the file was 48// exactly cap bytes (RC_EXACT) or the cap truncated it (RC_FULL, more remains). st[2] receives the probe rc. 49func rc_fill_file(fd: i64, buf: *u8, cap: i64, st: *i64) -> i64 { 50 let n: i64 = rc_fill(fd, buf, cap, st) 51 st[2] = 0 52 if st[0] == RC_CAPPED { 53 let probe: *u8 = sys_mmap(16) 54 let p: i64 = sys_read(fd, probe, RC_PROBE_BYTES) 55 st[2] = p 56 if p > 0 { st[0] = RC_FULL } else { if p == 0 { st[0] = RC_EXACT } else { st[0] = RC_ERR; st[1] = p } } 57 } 58 return n 59} 60 61// open + fill_file + close. A missing or unreadable file is RC_ERR with the open rc in st[1] and 0 bytes. 62func rc_read_file_into(path: *u8, buf: *u8, cap: i64, st: *i64) -> i64 { 63 let fd: i64 = sys_openat_rd(path) 64 if fd < 0 { st[0] = RC_ERR; st[1] = fd; st[2] = 0; return 0 } 65 let n: i64 = rc_fill_file(fd, buf, cap, st) 66 sys_close(fd) 67 return n 68} 69 70// 1 when the read is COMPLETE (EOF or EXACT), 0 when it is not (CAPPED, FULL, ERR) -- the one question a consumer 71// must ask before trusting buf as the whole source 72func rc_complete(st: *i64) -> i64 { 73 if st[0] == RC_EOF { return 1 } 74 if st[0] == RC_EXACT { return 1 } 75 return 0 76} 77 78func rc_state_name(s: i64) -> *u8 { 79 if s == RC_EOF { return "EOF" as *u8 } 80 if s == RC_CAPPED { return "CAPPED-unprobed" as *u8 } 81 if s == RC_FULL { return "TRUNCATED-more-remains" as *u8 } 82 if s == RC_EXACT { return "EXACT" as *u8 } 83 return "ERR" as *u8 84}