code wiki / _hdl_build / nx_seg_schema.nx
nx_seg_schema.nx source
↩ module page · 69 lines · 3256 B
1// nx_seg_schema.nx -- CAP-SEG-SCHEMA: a self-describing schema + typing + backward/forward EVOLUTION layer for the
2// sovereign store (Avro-class). A schema = ordered fields {name, type, required}. It is SELF-DESCRIBING (sc_encode
3// packs it to bytes storable as a store record; sc_decode reads it back). Evolution safety is MECHANIZED and matches
4// the API-contract-stability doctrine: a new schema is a SAFE evolution of the old iff it (a) keeps every old field
5// with the same type -- no remove/rename/retype -- and (b) adds only OPTIONAL fields (a new REQUIRED field breaks old
6// records). A LIBRARY (no main -> run its _gate). license_tier: ORIGINAL
7import "nx_syscalls.nx"
8
9const SC_STR: i64 = 1
10const SC_INT: i64 = 2
11const SC_BYTES: i64 = 3
12const SC_OPT: i64 = 0
13const SC_REQ: i64 = 1
14const SC_SAFE: i64 = 0
15const SC_REMOVED: i64 = 1
16const SC_RETYPED: i64 = 2
17const SC_NEWREQ: i64 = 3
18
19func sc_streq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 } if b[i]!=(0 as u8) { return 0 } return 1 }
20func sc_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
21func sc_w32(p: *u8, o: i64, v: i64) -> i64 { p[o]=((v>>24)&0xff) as u8; p[o+1]=((v>>16)&0xff) as u8; p[o+2]=((v>>8)&0xff) as u8; p[o+3]=(v&0xff) as u8; return o+4 }
22func sc_r32(p: *u8, o: i64) -> i64 { let a: i64=p[o]; let b: i64=p[o+1]; let c: i64=p[o+2]; let d: i64=p[o+3]; return (((((a<<8)|b)<<8)|c)<<8)|d }
23func sc_find(name: *u8, names: *i64, n: i64) -> i64 { var i: i64=0; while i<n { if sc_streq((names[i]) as *u8, name)==1 { return i } i=i+1 } return 0-1 }
24
25// self-describing encode: [u32be n] then per field [u8 type][u8 req][u32be namelen][name]. Returns bytes written.
26func sc_encode(n: i64, names: *i64, types: *i64, req: *i64, out: *u8) -> i64 {
27 var o: i64 = sc_w32(out, 0, n)
28 var i: i64=0
29 while i < n {
30 out[o]=types[i] as u8; o=o+1
31 out[o]=req[i] as u8; o=o+1
32 let nm: *u8 = (names[i]) as *u8; let nl: i64 = sc_slen(nm)
33 o = sc_w32(out, o, nl)
34 var k: i64=0; while k<nl { out[o]=nm[k]; o=o+1; k=k+1 }
35 i=i+1
36 }
37 return o
38}
39// decode into parallel arrays; returns field count.
40func sc_decode(b: *u8, out_names: *i64, out_types: *i64, out_req: *i64) -> i64 {
41 let n: i64 = sc_r32(b, 0); var o: i64 = 4
42 var i: i64=0
43 while i < n {
44 out_types[i] = b[o]; o=o+1
45 out_req[i] = b[o]; o=o+1
46 let nl: i64 = sc_r32(b, o); o=o+4
47 let nm: *u8 = sys_mmap(nl+1); var k: i64=0; while k<nl { nm[k]=b[o]; o=o+1; k=k+1 } nm[nl]=0 as u8
48 out_names[i] = nm as i64
49 i=i+1
50 }
51 return n
52}
53// is v2 a SAFE backward/forward evolution of v1? SC_SAFE / SC_REMOVED / SC_RETYPED / SC_NEWREQ.
54func sc_compat(n1: i64, names1: *i64, types1: *i64, n2: i64, names2: *i64, types2: *i64, req2: *i64) -> i64 {
55 var i: i64=0
56 while i < n1 {
57 let j: i64 = sc_find((names1[i]) as *u8, names2, n2)
58 if j < 0 { return SC_REMOVED }
59 if types2[j] != types1[i] { return SC_RETYPED }
60 i=i+1
61 }
62 i=0
63 while i < n2 {
64 let j: i64 = sc_find((names2[i]) as *u8, names1, n1)
65 if j < 0 { if req2[i] == SC_REQ { return SC_NEWREQ } }
66 i=i+1
67 }
68 return SC_SAFE
69}