nx_json_test.nx source
↩ module page · 114 lines · 3530 B
1// nx_json_test.nx -- exercise both the tokenizer (nx_json.nx) and the
2// emitter (nx_json_emit.nx) end-to-end.
3//
4// Strategy:
5// 1. Use the emitter to build an object with strings (incl.
6// escapes), ints, bool, null, nested array/object.
7// 2. Confirm the emitted bytes parse cleanly via the tokenizer.
8// 3. Spot-check a handful of token kinds + escape behaviour.
9
10import "nx_syscalls.nx"
11import "nx_runtime.nx"
12import "nx_json.nx"
13import "nx_json_emit.nx"
14import "json_emit.nx" // the RFC 8259 JsonWriter API this test actually exercises. nx_json_emit.nx
15 // is a DIFFERENT organ -- the tiny je_* emitter -- and never carried it.
16
17func main() -> i64 {
18 // ===== Emit phase ===============================================
19 let buf: *u8 = sys_mmap(512)
20 let w_raw: *u8 = sys_mmap(128)
21 let w: *JsonWriter = w_raw as *JsonWriter
22 json_writer_init(w, buf, 512)
23
24 json_begin_object(w)
25
26 json_emit_key(w, "who", 3)
27 json_emit_string(w, "sketch_hll", 10)
28
29 json_emit_key(w, "msg", 3)
30 // Contains a quote + backslash to exercise escape paths.
31 json_emit_string(w, "has \"quotes\" and \\back", 22)
32
33 json_emit_key(w, "count", 5)
34 json_emit_int(w, 42)
35
36 json_emit_key(w, "negative", 8)
37 json_emit_int(w, 0 - 7)
38
39 json_emit_key(w, "active", 6)
40 json_emit_bool(w, 1)
41
42 json_emit_key(w, "missing", 7)
43 json_emit_null(w)
44
45 json_emit_key(w, "tags", 4)
46 json_begin_array(w)
47 json_emit_string(w, "alpha", 5)
48 json_emit_string(w, "beta", 4)
49 json_end_array(w)
50
51 json_end_object(w)
52
53 let total: i64 = w.pos
54 if total <= 0 { return 1 }
55 // First byte is '{'.
56 if buf[0] != 0x7B { return 2 }
57 // Last emitted byte is '}'.
58 if buf[total - 1] != 0x7D { return 3 }
59
60 // ===== Tokenizer phase ==========================================
61 let t: *NxJsonTok = nx_json_new(buf, total)
62
63 // Token 1: LBRACE.
64 nx_json_next(t)
65 if t.kind != NX_JSON_LBRACE { return 4 }
66
67 // Token 2: STRING "who".
68 nx_json_next(t)
69 if t.kind != NX_JSON_STRING { return 5 }
70
71 // Token 3: COLON.
72 nx_json_next(t)
73 if t.kind != NX_JSON_COLON { return 6 }
74
75 // Token 4: STRING "sketch_hll".
76 nx_json_next(t)
77 if t.kind != NX_JSON_STRING { return 7 }
78
79 // Token 5: COMMA.
80 nx_json_next(t)
81 if t.kind != NX_JSON_COMMA { return 8 }
82
83 // Token 6: STRING "msg" (the escaped one's KEY).
84 nx_json_next(t)
85 if t.kind != NX_JSON_STRING { return 9 }
86
87 // Skip COLON + escaped-string value + COMMA.
88 nx_json_next(t)
89 if t.kind != NX_JSON_COLON { return 10 }
90 nx_json_next(t)
91 if t.kind != NX_JSON_STRING { return 11 }
92 // The escaped string's span includes the quotes; verify its first
93 // byte is `"` and last byte is `"`.
94 if buf[t.tok_off] != 0x22 { return 12 }
95 if buf[t.tok_off + t.tok_len - 1] != 0x22 { return 13 }
96
97 nx_json_next(t)
98 if t.kind != NX_JSON_COMMA { return 14 }
99
100 // "count":42
101 nx_json_next(t) // STRING key
102 if t.kind != NX_JSON_STRING { return 15 }
103 nx_json_next(t) // COLON
104 if t.kind != NX_JSON_COLON { return 16 }
105 nx_json_next(t) // NUMBER 42
106 if t.kind != NX_JSON_NUMBER { return 17 }
107
108 // We don't drain to EOF -- enough to confirm the emitter produced
109 // tokenizer-clean JSON across object + array + escape + int +
110 // negative + bool + null paths.
111
112 println("nx_json: emitter + tokenizer round-trip PASS" as *u8)
113 return 0
114}