json.bend

bend-kit-json@0.5.0.1 · 925 lines · 0 definitions

1# JSON values, parsed and encoded as RFC 8259. Source: https://github.com/paymog/bend-kit/tree/main/json
2import Base
3import bend-kit-bytes@0.3.0.0/bytes.bend as Bytes
4
5# JSON (RFC 8259) as UTF-8 in Bytes. Strings, numbers and object keys are
6# UTF-8 Bytes too. Nesting has no depth limit other than input size: the parser
7# keeps its own stack, since a Bend def cannot call itself through another def.
8#   import ./json/json.bend as Json
9
10# Num keeps the number's exact text, so no precision is lost. Obj keeps its
11# fields in document order, repeated keys included.
12type Val is Type:
13  Null{}
14  Flag{on: Bool}
15  Num{s: Bytes.Bytes}
16  Str{s: Bytes.Bytes}
17  Arr{xs: List<&1, Val>}
18  Obj{kvs: List<&1, Bytes.Bytes & Val>}
19
20# An open container: array items so far, object fields so far, or those fields
21# and the key whose value comes next. Items and fields are reversed.
22type Open is Type:
23  OArr{xs: List<&1, Val>}
24  OObj{kvs: List<&1, Bytes.Bytes & Val>}
25  OKey{kvs: List<&1, Bytes.Bytes & Val>, key: Bytes.Bytes}
26
27# Writer
28# ------
29# Octets being written: the buffer, its size in words, the count so far, and
30# the word being filled. Bytes enter at the top of w, as in Bytes.from_string.
31type W is Type:
32  W{buf: Array<U32>, cap: U32, n: U32, w: U32}
33
34# The buffer doubles when word k does not fit.
35def w.room(grow: Bool, buf: Array<U32>, +k: U32) -> Array<U32>:
36  match grow:
37    case True{}:
38      Bytes.grow((k * 4 : U32), buf, (k * 8 : U32))
39    case False{}:
40      buf
41
42def w.store(full: Bool, buf: Array<U32>, +cap: U32, +n: U32, +w: U32) -> W:
43  match full:
44    case True{}:
45      +k = (n >> 2n : U32)
46      +g = U32.is_eq(k, cap)
47      W{Array.set(U32, w.room(g, buf, k), k, w), Bool.pick(U32, g, (cap * 2 : U32), cap), (n + 1 : U32), 0}
48    case False{}:
49      W{buf, cap, (n + 1 : U32), w}
50
51def w.put(o: W, +b: U32) -> W:
52  W{buf, +cap, +n, +w} = o
53  w.store(U32.is_eq((n .&. 3 : U32), 3), buf, cap, n, ((w >> 8n) .|. (b << 24n) : U32))
54
55def w.shrink(fit: Bool, +n: U32, buf: Array<U32>) -> Array<U32>:
56  match fit:
57    case True{}:
58      buf
59    case False{}:
60      Bytes.dst(Bytes.copy(n, buf, Bytes.alloc(n), 0, 0))
61
62# Stores the last partial word, then copies into the fewest words, as Bytes requires.
63def w.done(o: W) -> Bytes.Bytes:
64  W{buf, +cap, +n, +w} = o
65  +r = (n .&. 3 : U32)
66  +k = (n >> 2n : U32)
67  +g = U32.is_ne(r, 0) && U32.is_eq(k, cap)
68  +cap2 = Bool.pick(U32, g, (cap * 2 : U32), cap)
69  out = Bytes.flush(U32.is_ne(r, 0), w.room(g, buf, k), k, U32.shrn(w, U32.to_nat((((4 - r) .&. 3) * 8 : U32))))
70  Bytes.Bytes{n, w.shrink(U32.is_eq(U32.shln(1, Bytes.depth(Bytes.words(n))), cap2), n, out)}
71
72def w.cont(+c: U32, +k: Nat) -> U32:
73  (128 + (U32.shrn(c, k) .&. 63) : U32)
74
75def w.cp.of(+n: U32, +c: U32, o: W) -> W:
76  match n:
77    case 1:
78      w.put(o, c)
79    case 2:
80      w.put(w.put(o, (192 + U32.shrn(c, 6n) : U32)), w.cont(c, 0n))
81    case 3:
82      w.put(w.put(w.put(o, (224 + U32.shrn(c, 12n) : U32)), w.cont(c, 6n)), w.cont(c, 0n))
83    case _:
84      w.put(w.put(w.put(w.put(o, (240 + U32.shrn(c, 18n) : U32)), w.cont(c, 12n)), w.cont(c, 6n)), w.cont(c, 0n))
85
86# One code point in UTF-8.
87def w.cp(+c: U32, o: W) -> W:
88  w.cp.of(Bool.pick(U32, U32.is_lt(c, 128), 1, Bool.pick(U32, U32.is_lt(c, 2048), 2, Bool.pick(U32, U32.is_lt(c, 65536), 3, 4))), c, o)
89
90def w.hex(+n: U32) -> U32:
91  Bool.pick(U32, U32.is_lt(n, 10), (48 + n : U32), (87 + n : U32))
92
93def w.new() -> W:
94  W{Bytes.alloc(0), 1, 0, 0}
95
96def w.of.at(+len: U32, +cap: U32, r: Array<U32> & U32) -> W:
97  (buf, +v) = r
98  +m = (len .&. 3 : U32)
99  W{buf, cap, len, Bool.pick(U32, U32.is_eq(m, 0), 0, U32.shln(v, U32.to_nat(((4 - m) * 8 : U32))))}
100
101# A writer that appends to b.
102def w.of(b: Bytes.Bytes) -> W:
103  Bytes.Bytes{+len, buf} = b
104  w.of.at(len, U32.shln(1, Bytes.depth(Bytes.words(len))), Array.get(U32, buf, (len >> 2n : U32)))
105
106def w.text(s: String, o: W) -> W:
107  match s:
108    case SNil{}:
109      o
110    case SCon{Chr{+c}, t}:
111      w.text(t, w.cp(c, o))
112
113# Text, one Char per code point, as UTF-8.
114def utf8(s: String) -> Bytes.Bytes:
115  w.done(w.text(s, w.new()))
116
117# Numbers (§6)
118# ------------
119# States: 0 start, 1 after "-", 2 after a leading "0", 3 int digits, 4 after
120# ".", 5 fraction digits, 6 after "e", 7 after the exponent sign, 8 exponent
121# digits. 99 means the char does not continue the number.
122
123def digit(+c: U32) -> Bool:
124  Bool.and(U32.is_le(48, c), U32.is_le(c, 57))
125
126def num.trans(+st: U32, +c: U32) -> U32:
127  +d = digit(c)
128  +z = U32.is_eq(c, 48)
129  +dot = U32.is_eq(c, 46)
130  +e = Bool.or(U32.is_eq(c, 101), U32.is_eq(c, 69))
131  +sign = Bool.or(U32.is_eq(c, 43), U32.is_eq(c, 45))
132  Bool.pick(U32, U32.is_eq(st, 0), Bool.pick(U32, U32.is_eq(c, 45), 1, Bool.pick(U32, z, 2, Bool.pick(U32, d, 3, 99))),
133  Bool.pick(U32, U32.is_eq(st, 1), Bool.pick(U32, z, 2, Bool.pick(U32, d, 3, 99)),
134  Bool.pick(U32, Bool.or(U32.is_eq(st, 2), U32.is_eq(st, 3)), Bool.pick(U32, Bool.and(d, U32.is_eq(st, 3)), 3, Bool.pick(U32, dot, 4, Bool.pick(U32, e, 6, 99))),
135  Bool.pick(U32, Bool.or(U32.is_eq(st, 4), U32.is_eq(st, 5)), Bool.pick(U32, d, 5, Bool.pick(U32, Bool.and(e, U32.is_eq(st, 5)), 6, 99)),
136  Bool.pick(U32, U32.is_eq(st, 6), Bool.pick(U32, sign, 7, Bool.pick(U32, d, 8, 99)),
137  Bool.pick(U32, Bool.or(U32.is_eq(st, 7), U32.is_eq(st, 8)), Bool.pick(U32, d, 8, 99), 99))))))
138
139def num.accepts(+st: U32) -> Bool:
140  Bool.or(Bool.or(U32.is_eq(st, 2), U32.is_eq(st, 3)), Bool.or(U32.is_eq(st, 5), U32.is_eq(st, 8)))
141
142# Strings (§7)
143# ------------
144
145def hexd(+c: U32) -> U32:
146  Bool.pick(U32, digit(c), (c - 48 : U32), Bool.pick(U32, Bool.and(U32.is_le(97, c), U32.is_le(c, 102)), (c - 87 : U32), Bool.pick(U32, Bool.and(U32.is_le(65, c), U32.is_le(c, 70)), (c - 55 : U32), 99)))
147
148def is_hi(+v: U32) -> Bool:
149  Bool.and(U32.is_le(55296, v), U32.is_le(v, 56319))
150
151def is_lo(+v: U32) -> Bool:
152  Bool.and(U32.is_le(56320, v), U32.is_le(v, 57343))
153
154def esc.simple(+e: U32) -> U32:
155  Bool.pick(U32, U32.is_eq(e, 34), 34, Bool.pick(U32, U32.is_eq(e, 92), 92, Bool.pick(U32, U32.is_eq(e, 47), 47,
156  Bool.pick(U32, U32.is_eq(e, 98), 8, Bool.pick(U32, U32.is_eq(e, 102), 12, Bool.pick(U32, U32.is_eq(e, 110), 10,
157  Bool.pick(U32, U32.is_eq(e, 114), 13, Bool.pick(U32, U32.is_eq(e, 116), 9, 99))))))))
158
159# Parse
160# -----
161# A state holds the offset of its next byte; the buffer goes beside it. A
162# string with no escape is copied out of the buffer when it closes; at its
163# first escape it moves into a writer.
164
165type Sb is Type:
166  BValue{i: U32, stack: List<&1, Open>}
167  BFirst{i: U32, open: Open, stack: List<&1, Open>}
168  BKey{i: U32, stack: List<&1, Open>}
169  BColon{key: Bytes.Bytes, i: U32, stack: List<&1, Open>}
170  BStr{i: U32, start: U32, key: Bool, stack: List<&1, Open>}
171  BEsc{i: U32, acc: W, key: Bool, stack: List<&1, Open>}
172  BNum{i: U32, start: U32, st: U32, stack: List<&1, Open>}
173  BAfter{v: Val, i: U32, stack: List<&1, Open>}
174  BSep{i: U32, open: Open, stack: List<&1, Open>}
175  BEnd{v: Val, i: U32}
176  BOk{v: Val}
177  BFail{}
178
179type Cp is Data:
180  Cp{c: U32, w: U32}
181
182def pk.if(ok: Bool, a: Array<U32>, +i: U32) -> Array<U32> & U32:
183  match ok:
184    case True{}:
185      Bytes.peek(a, i)
186    case False{}:
187      (a, 256)
188
189# Byte i, or 256 at the end, which no rule accepts.
190def pk(a: Array<U32>, +len: U32, +i: U32) -> Array<U32> & U32:
191  pk.if(U32.is_lt(i, len), a, i)
192
193def is_ws(+c: U32) -> Bool:
194  U32.is_eq(c, 32) || U32.is_eq(c, 9) || U32.is_eq(c, 10) || U32.is_eq(c, 13)
195
196# A string byte that needs no check: ASCII, not a control, quote or backslash.
197def plain(+c: U32) -> Bool:
198  U32.is_le(32, c) && U32.is_lt(c, 128) && U32.is_ne(c, 34) && U32.is_ne(c, 92)
199
200def pos.of(+i: U32, r: Array<U32> & U32) -> Array<U32> & U32 & U32:
201  (a, +c) = r
202  (a, i, c)
203
204# The offset i and its byte.
205def pos(a: Array<U32>, +len: U32, +i: U32) -> Array<U32> & U32 & U32:
206  pos.of(i, pk(a, len, i))
207
208def run.cls(~ok: @+c: U32 -> Bool, r: Array<U32> & U32) -> Array<U32> & U32 & Bool:
209  (a, +c) = r
210  (a, c, ok(c))
211
212# g bounds the loop; it is the parser's fuel, shared, so no count is built per run.
213def run.go(~ok: @+c: U32 -> Bool, g: Nat, r: Array<U32> & U32 & Bool, +len: U32, +i: U32) -> Array<U32> & U32 & U32:
214  match g:
215    case 0n:
216      (a, +c, more) = r
217      (a, i, c)
218    case 1n+h:
219      (a, +c, more) = r
220      match more:
221        case True{}:
222          run.go(~ok, h, run.cls(~ok, pk(a, len, (i + 1 : U32))), len, (i + 1 : U32))
223        case False{}:
224          (a, i, c)
225
226# The first offset from i whose byte is not ok, and that byte.
227def run(~ok: @+c: U32 -> Bool, +g: Nat, a: Array<U32>, +len: U32, +i: U32) -> Array<U32> & U32 & U32:
228  run.go(~ok, g, run.cls(~ok, pk(a, len, i)), len, i)
229
230def word.go(w: String, ok: Bool, r: Array<U32> & U32, +len: U32, +j: U32) -> Array<U32> & Bool:
231  match w:
232    case SNil{}:
233      (a, b) = r
234      (a, ok)
235    case SCon{Chr{+c}, t}:
236      (a, +b) = r
237      word.go(t, ok && U32.is_eq(b, c), pk(a, len, (j + 1 : U32)), len, (j + 1 : U32))
238
239# Do the bytes from j spell w?
240def word(a: Array<U32>, +len: U32, w: String, +j: U32) -> Array<U32> & Bool:
241  word.go(w, True{}, pk(a, len, j), len, j)
242
243def hex4.b.go(n: Nat, r: Array<U32> & U32, +len: U32, +j: U32, +acc: U32) -> Array<U32> & U32:
244  match n:
245    case 0n:
246      (a, b) = r
247      (a, acc)
248    case 1n+k:
249      (a, +b) = r
250      +h = hexd(b)
251      hex4.b.go(k, pk(a, len, (j + 1 : U32)), len, (j + 1 : U32), Bool.pick(U32, U32.is_eq(h, 99) || U32.is_eq(acc, 65536), 65536, (acc * 16 + h : U32)))
252
253# Four hex digits from byte j, or 65536 if one is not a hex digit.
254def hex4.b(a: Array<U32>, +len: U32, +j: U32) -> Array<U32> & U32:
255  hex4.b.go(4n, pk(a, len, j), len, j, 0)
256
257def cont(+b: U32) -> Bool:
258  U32.is_eq((b .&. 192 : U32), 128)
259
260# RFC 3629 §4: overlong forms, surrogates, and code points past U+10FFFF are invalid, width 0.
261def utf8.n(+b0: U32, +b1: U32, +b2: U32, +b3: U32) -> Cp:
262  +x1 = (b1 .&. 63 : U32)
263  +x2 = (b2 .&. 63 : U32)
264  +x3 = (b3 .&. 63 : U32)
265  +c2 = (((b0 .&. 31) << 6n) .|. x1 : U32)
266  +c3 = ((((b0 .&. 15) << 12n) .|. (x1 << 6n)) .|. x2 : U32)
267  +c4 = (((((b0 .&. 7) << 18n) .|. (x1 << 12n)) .|. (x2 << 6n)) .|. x3 : U32)
268  +ok2 = U32.is_le(192, b0) && U32.is_lt(b0, 224) && cont(b1) && U32.is_le(128, c2)
269  +ok3 = U32.is_le(224, b0) && U32.is_lt(b0, 240) && cont(b1) && cont(b2) && U32.is_le(2048, c3) && (U32.is_lt(c3, 55296) || U32.is_lt(57343, c3))
270  +ok4 = U32.is_le(240, b0) && U32.is_lt(b0, 248) && cont(b1) && cont(b2) && cont(b3) && U32.is_le(65536, c4) && U32.is_le(c4, 1114111)
271  Bool.pick(Cp, ok2, Cp{c2, 2}, Bool.pick(Cp, ok3, Cp{c3, 3}, Bool.pick(Cp, ok4, Cp{c4, 4}, Cp{0, 0})))
272
273def utf8.b3(+b0: U32, +b1: U32, +b2: U32, r: Array<U32> & U32) -> Array<U32> & Cp:
274  (a, +b3) = r
275  (a, utf8.n(b0, b1, b2, b3))
276
277def utf8.b2(+len: U32, +i: U32, +b0: U32, +b1: U32, r: Array<U32> & U32) -> Array<U32> & Cp:
278  (a, +b2) = r
279  utf8.b3(b0, b1, b2, pk(a, len, (i + 3 : U32)))
280
281def utf8.b1(+len: U32, +i: U32, +b0: U32, r: Array<U32> & U32) -> Array<U32> & Cp:
282  (a, +b1) = r
283  utf8.b2(len, i, b0, b1, pk(a, len, (i + 2 : U32)))
284
285# The code point whose lead byte b0 is at i.
286def utf8.at(a: Array<U32>, +len: U32, +i: U32, +b0: U32) -> Array<U32> & Cp:
287  utf8.b1(len, i, b0, pk(a, len, (i + 1 : U32)))
288
289def slice.of(+n: U32, r: Array<U32> & Array<U32>) -> Array<U32> & Bytes.Bytes:
290  (a, out) = r
291  (a, Bytes.Bytes{n, out})
292
293# The n bytes from start, copied.
294def slice(+n: U32, +start: U32, a: Array<U32>) -> Array<U32> & Bytes.Bytes:
295  slice.of(n, Bytes.copy(n, a, Bytes.alloc(n), start, 0))
296
297def str.b.done(key: Bool, s: Bytes.Bytes, +i: U32, stack: List<&1, Open>) -> Sb:
298  match key:
299    case True{}:
300      BColon{s, i, stack}
301    case False{}:
302      BAfter{Str{s}, i, stack}
303
304def esc.b.lo.if(ok: Bool, +i: U32, +hi: U32, +lo: U32, acc: W, key: Bool, stack: List<&1, Open>) -> Sb:
305  match ok:
306    case True{}:
307      BEsc{(i + 12 : U32), w.cp((65536 + (hi - 55296 : U32) * 1024 + (lo - 56320 : U32) : U32), acc), key, stack}
308    case False{}:
309      BEsc{(i + 6 : U32), w.cp(65533, acc), key, stack}
310
311def esc.b.lo(+i: U32, +hi: U32, acc: W, key: Bool, stack: List<&1, Open>, r: Array<U32> & U32) -> Array<U32> & Sb:
312  (a, +lo) = r
313  (a, esc.b.lo.if(is_lo(lo), i, hi, lo, acc, key, stack))
314
315# §8.2: a high surrogate pairs with a following \uDC00-\uDFFF; a lone one is U+FFFD.
316def esc.b.pair(+len: U32, +i: U32, +hi: U32, acc: W, key: Bool, stack: List<&1, Open>, r: Array<U32> & Bool) -> Array<U32> & Sb:
317  (a, ok) = r
318  match ok:
319    case True{}:
320      esc.b.lo(i, hi, acc, key, stack, hex4.b(a, len, (i + 8 : U32)))
321    case False{}:
322      (a, BEsc{(i + 6 : U32), w.cp(65533, acc), key, stack})
323
324# 0: not four hex digits; 1: high surrogate; 2: low surrogate; 3: other.
325def u.class(+v: U32) -> U32:
326  Bool.pick(U32, U32.is_eq(v, 65536), 0, Bool.pick(U32, is_hi(v), 1, Bool.pick(U32, is_lo(v), 2, 3)))
327
328def esc.b.u.of(+k: U32, a: Array<U32>, +len: U32, +i: U32, +v: U32, acc: W, key: Bool, stack: List<&1, Open>) -> Array<U32> & Sb:
329  match k:
330    case 0:
331      (a, BFail{})
332    case 1:
333      esc.b.pair(len, i, v, acc, key, stack, word(a, len, "\\u", (i + 6 : U32)))
334    case 2:
335      (a, BEsc{(i + 6 : U32), w.cp(65533, acc), key, stack})
336    case _:
337      (a, BEsc{(i + 6 : U32), w.cp(v, acc), key, stack})
338
339def esc.b.u(+len: U32, +i: U32, acc: W, key: Bool, stack: List<&1, Open>, r: Array<U32> & U32) -> Array<U32> & Sb:
340  (a, +v) = r
341  esc.b.u.of(u.class(v), a, len, i, v, acc, key, stack)
342
343# The escape whose backslash is at i.
344def esc.b.one(+len: U32, +i: U32, acc: W, key: Bool, stack: List<&1, Open>, r: Array<U32> & U32) -> Array<U32> & Sb:
345  (a, +e) = r
346  match e:
347    case 117:
348      esc.b.u(len, i, acc, key, stack, hex4.b(a, len, (i + 2 : U32)))
349    case _:
350      +v = esc.simple(e)
351      (a, Bool.pick(Sb, U32.is_eq(v, 99), BFail{}, BEsc{(i + 2 : U32), w.put(acc, v), key, stack}))
352
353def esc.b.cp(acc: W, key: Bool, stack: List<&1, Open>, +i: U32, r: Array<U32> & Cp) -> Array<U32> & Sb:
354  (a, Cp{+c, +n}) = r
355  (a, Bool.pick(Sb, U32.is_eq(n, 0), BFail{}, BEsc{(i + n : U32), w.cp(c, acc), key, stack}))
356
357# §7: unescaped chars below U+0020 are not allowed in a string.
358def esc.b.other(ascii: Bool, +c: U32, a: Array<U32>, +len: U32, +i: U32, acc: W, key: Bool, stack: List<&1, Open>) -> Array<U32> & Sb:
359  match ascii:
360    case True{}:
361      (a, Bool.pick(Sb, U32.is_lt(c, 32), BFail{}, BEsc{(i + 1 : U32), w.put(acc, c), key, stack}))
362    case False{}:
363      esc.b.cp(acc, key, stack, i, utf8.at(a, len, i, c))
364
365# A string after its first escape.
366def esc.b(r: Array<U32> & U32, +len: U32, +i: U32, acc: W, key: Bool, stack: List<&1, Open>) -> Array<U32> & Sb:
367  (a, +c) = r
368  match c:
369    case 34:
370      (a, str.b.done(key, w.done(acc), (i + 1 : U32), stack))
371    case 92:
372      esc.b.one(len, i, acc, key, stack, pk(a, len, (i + 1 : U32)))
373    case 256:
374      (a, BFail{})
375    case _:
376      esc.b.other(U32.is_lt(c, 128), c, a, len, i, acc, key, stack)
377
378def str.b.close(key: Bool, +i: U32, stack: List<&1, Open>, r: Array<U32> & Bytes.Bytes) -> Array<U32> & Sb:
379  (a, s) = r
380  (a, str.b.done(key, s, (i + 1 : U32), stack))
381
382def str.b.esc(+len: U32, +i: U32, key: Bool, stack: List<&1, Open>, r: Array<U32> & Bytes.Bytes) -> Array<U32> & Sb:
383  (a, s) = r
384  esc.b.one(len, i, w.of(s), key, stack, pk(a, len, (i + 1 : U32)))
385
386def str.b.cp(+start: U32, key: Bool, stack: List<&1, Open>, +i: U32, r: Array<U32> & Cp) -> Array<U32> & Sb:
387  (a, Cp{+c, +n}) = r
388  (a, Bool.pick(Sb, U32.is_eq(n, 0), BFail{}, BStr{(i + n : U32), start, key, stack}))
389
390def str.b.other(ascii: Bool, +c: U32, a: Array<U32>, +len: U32, +i: U32, +start: U32, key: Bool, stack: List<&1, Open>) -> Array<U32> & Sb:
391  match ascii:
392    case True{}:
393      (a, Bool.pick(Sb, U32.is_lt(c, 32), BFail{}, BStr{(i + 1 : U32), start, key, stack}))
394    case False{}:
395      str.b.cp(start, key, stack, i, utf8.at(a, len, i, c))
396
397# A string whose text so far starts at start and has no escape.
398def str.b(r: Array<U32> & U32, +len: U32, +i: U32, +start: U32, key: Bool, stack: List<&1, Open>) -> Array<U32> & Sb:
399  (a, +c) = r
400  match c:
401    case 34:
402      str.b.close(key, i, stack, slice((i - start : U32), start, a))
403    case 92:
404      str.b.esc(len, i, key, stack, slice((i - start : U32), start, a))
405    case 256:
406      (a, BFail{})
407    case _:
408      str.b.other(U32.is_lt(c, 128), c, a, len, i, start, key, stack)
409
410def num.b.fin(+i: U32, stack: List<&1, Open>, r: Array<U32> & Bytes.Bytes) -> Array<U32> & Sb:
411  (a, s) = r
412  (a, BAfter{Num{s}, i, stack})
413
414def num.b.stop(ok: Bool, a: Array<U32>, +i: U32, +start: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
415  match ok:
416    case True{}:
417      num.b.fin(i, stack, slice((i - start : U32), start, a))
418    case False{}:
419      (a, BFail{})
420
421def num.b.if(stop: Bool, a: Array<U32>, +i: U32, +start: U32, +st: U32, +n: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
422  match stop:
423    case True{}:
424      num.b.stop(num.accepts(st), a, i, start, stack)
425    case False{}:
426      (a, BNum{(i + 1 : U32), start, n, stack})
427
428def num.b(r: Array<U32> & U32, +i: U32, +start: U32, +st: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
429  (a, +c) = r
430  +n = num.trans(st, c)
431  num.b.if(U32.is_eq(n, 99), a, i, start, st, n, stack)
432
433def lit.b(+i: U32, +n: U32, v: Val, stack: List<&1, Open>, r: Array<U32> & Bool) -> Array<U32> & Sb:
434  (a, ok) = r
435  match ok:
436    case True{}:
437      (a, BAfter{v, (i + n : U32), stack})
438    case False{}:
439      (a, BFail{})
440
441def value.b(r: Array<U32> & U32, +len: U32, +i: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
442  (a, +c) = r
443  match c:
444    case 32:
445      (a, BValue{(i + 1 : U32), stack})
446    case 9:
447      (a, BValue{(i + 1 : U32), stack})
448    case 10:
449      (a, BValue{(i + 1 : U32), stack})
450    case 13:
451      (a, BValue{(i + 1 : U32), stack})
452    case 91:
453      (a, BFirst{(i + 1 : U32), OArr{Nil{}}, stack})
454    case 123:
455      (a, BFirst{(i + 1 : U32), OObj{Nil{}}, stack})
456    case 34:
457      (a, BStr{(i + 1 : U32), (i + 1 : U32), False{}, stack})
458    case 116:
459      lit.b(i, 4, Flag{True{}}, stack, word(a, len, "true", i))
460    case 102:
461      lit.b(i, 5, Flag{False{}}, stack, word(a, len, "false", i))
462    case 110:
463      lit.b(i, 4, Null{}, stack, word(a, len, "null", i))
464    case _:
465      (a, BNum{i, i, 0, stack})
466
467# After "[" or "{": the closing bracket, or the first item.
468def first.b.end(open: Open, +c: U32, +i: U32, stack: List<&1, Open>) -> Sb:
469  match open:
470    case OArr{xs}:
471      Bool.pick(Sb, U32.is_eq(c, 93), BAfter{Arr{xs}, (i + 1 : U32), stack}, BFail{})
472    case OObj{kvs}:
473      Bool.pick(Sb, U32.is_eq(c, 125), BAfter{Obj{kvs}, (i + 1 : U32), stack}, BFail{})
474    case OKey{kvs, k}:
475      BFail{}
476
477def first.b.open(open: Open, +i: U32, stack: List<&1, Open>) -> Sb:
478  match open:
479    case OArr{xs}:
480      BValue{i, Con{OArr{xs}, stack}}
481    case OObj{kvs}:
482      BKey{i, Con{OObj{kvs}, stack}}
483    case OKey{kvs, k}:
484      BFail{}
485
486def first.b(r: Array<U32> & U32, +i: U32, open: Open, stack: List<&1, Open>) -> Array<U32> & Sb:
487  (a, +c) = r
488  match c:
489    case 32:
490      (a, BFirst{(i + 1 : U32), open, stack})
491    case 9:
492      (a, BFirst{(i + 1 : U32), open, stack})
493    case 10:
494      (a, BFirst{(i + 1 : U32), open, stack})
495    case 13:
496      (a, BFirst{(i + 1 : U32), open, stack})
497    case 93:
498      (a, first.b.end(open, c, i, stack))
499    case 125:
500      (a, first.b.end(open, c, i, stack))
501    case _:
502      (a, first.b.open(open, i, stack))
503
504def key.b(r: Array<U32> & U32, +i: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
505  (a, +c) = r
506  match c:
507    case 32:
508      (a, BKey{(i + 1 : U32), stack})
509    case 9:
510      (a, BKey{(i + 1 : U32), stack})
511    case 10:
512      (a, BKey{(i + 1 : U32), stack})
513    case 13:
514      (a, BKey{(i + 1 : U32), stack})
515    case 34:
516      (a, BStr{(i + 1 : U32), (i + 1 : U32), True{}, stack})
517    case _:
518      (a, BFail{})
519
520def colon.b.top(k: Bytes.Bytes, +i: U32, stack: List<&1, Open>) -> Sb:
521  match stack:
522    case Nil{}:
523      BFail{}
524    case Con{OArr{xs}, up}:
525      BFail{}
526    case Con{OObj{kvs}, up}:
527      BValue{i, Con{OKey{kvs, k}, up}}
528    case Con{OKey{kvs, old}, up}:
529      BFail{}
530
531def colon.b(r: Array<U32> & U32, k: Bytes.Bytes, +i: U32, stack: List<&1, Open>) -> Array<U32> & Sb:
532  (a, +c) = r
533  match c:
534    case 32:
535      (a, BColon{k, (i + 1 : U32), stack})
536    case 9:
537      (a, BColon{k, (i + 1 : U32), stack})
538    case 10:
539      (a, BColon{k, (i + 1 : U32), stack})
540    case 13:
541      (a, BColon{k, (i + 1 : U32), stack})
542    case 58:
543      (a, colon.b.top(k, (i + 1 : U32), stack))
544    case _:
545      (a, BFail{})
546
547# A finished value joins its container.
548def after.b(v: Val, +i: U32, stack: List<&1, Open>) -> Sb:
549  match stack:
550    case Nil{}:
551      BEnd{v, i}
552    case Con{OArr{xs}, up}:
553      BSep{i, OArr{Con{v, xs}}, up}
554    case Con{OObj{kvs}, up}:
555      BFail{}
556    case Con{OKey{kvs, k}, up}:
557      BSep{i, OObj{Con{(k, v), kvs}}, up}
558
559def sep.b.comma(open: Open, +i: U32, up: List<&1, Open>) -> Sb:
560  match open:
561    case OArr{xs}:
562      BValue{i, Con{OArr{xs}, up}}
563    case OObj{kvs}:
564      BKey{i, Con{OObj{kvs}, up}}
565    case OKey{kvs, k}:
566      BFail{}
567
568def sep.b.close(open: Open, +c: U32, +i: U32, up: List<&1, Open>) -> Sb:
569  match open:
570    case OArr{xs}:
571      Bool.pick(Sb, U32.is_eq(c, 93), BAfter{Arr{List.reverse(&1, Val, xs)}, i, up}, BFail{})
572    case OObj{kvs}:
573      Bool.pick(Sb, U32.is_eq(c, 125), BAfter{Obj{List.reverse(&1, Bytes.Bytes & Val, kvs)}, i, up}, BFail{})
574    case OKey{kvs, k}:
575      BFail{}
576
577# After an item: "," or the closing bracket.
578def sep.b(r: Array<U32> & U32, +i: U32, open: Open, up: List<&1, Open>) -> Array<U32> & Sb:
579  (a, +c) = r
580  match c:
581    case 32:
582      (a, BSep{(i + 1 : U32), open, up})
583    case 9:
584      (a, BSep{(i + 1 : U32), open, up})
585    case 10:
586      (a, BSep{(i + 1 : U32), open, up})
587    case 13:
588      (a, BSep{(i + 1 : U32), open, up})
589    case 44:
590      (a, sep.b.comma(open, (i + 1 : U32), up))
591    case _:
592      (a, sep.b.close(open, c, (i + 1 : U32), up))
593
594def end.b(r: Array<U32> & U32, v: Val, +i: U32) -> Array<U32> & Sb:
595  (a, +c) = r
596  match c:
597    case 32:
598      (a, BEnd{v, (i + 1 : U32)})
599    case 9:
600      (a, BEnd{v, (i + 1 : U32)})
601    case 10:
602      (a, BEnd{v, (i + 1 : U32)})
603    case 13:
604      (a, BEnd{v, (i + 1 : U32)})
605    case 256:
606      (a, BOk{v})
607    case _:
608      (a, BFail{})
609
610# A run's end (a, i, c) to each step. The parts bind without + (bendlang/bend#1077).
611def value.r(+len: U32, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
612  (a, i, c) = r
613  value.b((a, c), len, i, stack)
614
615def first.r(open: Open, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
616  (a, i, c) = r
617  first.b((a, c), i, open, stack)
618
619def key.r(stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
620  (a, i, c) = r
621  key.b((a, c), i, stack)
622
623def colon.r(k: Bytes.Bytes, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
624  (a, i, c) = r
625  colon.b((a, c), k, i, stack)
626
627def str.r(+len: U32, +s: U32, key: Bool, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
628  (a, i, c) = r
629  str.b((a, c), len, i, s, key, stack)
630
631def num.r(+s: U32, +st: U32, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
632  (a, i, c) = r
633  num.b((a, c), i, s, st, stack)
634
635def sep.r(open: Open, up: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
636  (a, i, c) = r
637  sep.b((a, c), i, open, up)
638
639def end.r(v: Val, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
640  (a, i, c) = r
641  end.b((a, c), v, i)
642
643def w.span.go(n: Nat, r: Array<U32> & U32, +i: U32, o: W) -> Array<U32> & W:
644  match n:
645    case 0n:
646      (a, v) = r
647      (a, o)
648    case 1n+k:
649      (a, +c) = r
650      w.span.go(k, Bytes.peek(a, (i + 1 : U32)), (i + 1 : U32), w.put(o, c))
651
652def esc.r.go(+len: U32, +j: U32, c: U32, key: Bool, stack: List<&1, Open>, r: Array<U32> & W) -> Array<U32> & Sb:
653  (a, acc) = r
654  esc.b((a, c), len, j, acc, key, stack)
655
656# The plain bytes from i to the run's end go onto acc in one loop.
657def esc.r(+len: U32, +i: U32, acc: W, key: Bool, stack: List<&1, Open>, r: Array<U32> & U32 & U32) -> Array<U32> & Sb:
658  (a, +j, c) = r
659  esc.r.go(len, j, c, key, stack, w.span.go(U32.to_nat((j - i : U32)), Bytes.peek(a, i), i, acc))
660
661# States 3, 5 and 8 take digits until the number's part ends.
662def num.run(loop: Bool, +g: Nat, a: Array<U32>, +len: U32, +i: U32) -> Array<U32> & U32 & U32:
663  match loop:
664    case True{}:
665      run(~digit, g, a, len, i)
666    case False{}:
667      pos(a, len, i)
668
669# fuel: a step eats a byte, or ends a number, a value, or an opening bracket, so 4 * len + 4 steps are enough.
670def runb(+fuel: Nat, r: Array<U32> & Sb, +len: U32) -> Maybe<&1, Val>:
671  match fuel:
672    case 0n:
673      None{}
674    case 1n+f:
675      (a, sb) = r
676      match sb:
677        case BOk{v}:
678          Some{v}
679        case BFail{}:
680          None{}
681        case BValue{+i, stack}:
682          runb(f, value.r(len, stack, run(~is_ws, f, a, len, i)), len)
683        case BFirst{+i, open, stack}:
684          runb(f, first.r(open, stack, run(~is_ws, f, a, len, i)), len)
685        case BKey{+i, stack}:
686          runb(f, key.r(stack, run(~is_ws, f, a, len, i)), len)
687        case BColon{k, +i, stack}:
688          runb(f, colon.r(k, stack, run(~is_ws, f, a, len, i)), len)
689        case BStr{+i, +s, k, stack}:
690          runb(f, str.r(len, s, k, stack, run(~plain, f, a, len, i)), len)
691        case BEsc{+i, acc, k, stack}:
692          runb(f, esc.r(len, i, acc, k, stack, run(~plain, f, a, len, i)), len)
693        case BNum{+i, +s, +st, stack}:
694          runb(f, num.r(s, st, stack, num.run(U32.is_eq(st, 3) || U32.is_eq(st, 5) || U32.is_eq(st, 8), f, a, len, i)), len)
695        case BAfter{v, +i, stack}:
696          runb(f, (a, after.b(v, i, stack)), len)
697        case BSep{+i, open, stack}:
698          runb(f, sep.r(open, stack, run(~is_ws, f, a, len, i)), len)
699        case BEnd{v, +i}:
700          runb(f, end.r(v, run(~is_ws, f, a, len, i)), len)
701
702# One JSON text in UTF-8. None for bad JSON or bad UTF-8 (RFC 8259 §8.1).
703def parse.bytes(b: Bytes.Bytes) -> Maybe<&1, Val>:
704  Bytes.Bytes{+len, buf} = b
705  runb(Nat.add(Nat.mul(U32.to_nat(len), 4n), 4n), (buf, BValue{0, Nil{}}), len)
706
707# Access
708# ------
709
710def get.pick(v: Val, found: Maybe<&1, Val>, r: Bytes.Bytes & Bytes.Bytes & Bool) -> Bytes.Bytes & Maybe<&1, Val>:
711  (k, key, same) = r
712  (key, Bool.pick(Maybe<&1, Val>, same, Some{v}, found))
713
714def get.step(k: Bytes.Bytes, v: Val, st: Bytes.Bytes & Maybe<&1, Val>) -> Bytes.Bytes & Maybe<&1, Val>:
715  (key, found) = st
716  get.pick(v, found, Bytes.eq(k, key))
717
718def get.go(kvs: List<&1, Bytes.Bytes & Val>, st: Bytes.Bytes & Maybe<&1, Val>) -> Maybe<&1, Val>:
719  match kvs:
720    case Nil{}:
721      (key, found) = st
722      found
723    case (k, v) <> t:
724      get.go(t, get.step(k, v, st))
725
726# §4: the value under key k of an object; the last one when k repeats, as most parsers do.
727def get(v: Val, k: String) -> Maybe<&1, Val>:
728  match v:
729    case Obj{kvs}:
730      get.go(kvs, (utf8(k), None{}))
731    case Null{}:
732      None{}
733    case Flag{on}:
734      None{}
735    case Num{n}:
736      None{}
737    case Str{s}:
738      None{}
739    case Arr{xs}:
740      None{}
741
742def at.go(xs: List<&1, Val>, n: Nat) -> Maybe<&1, Val>:
743  match xs:
744    case Nil{}:
745      None{}
746    case Con{v, t}:
747      match n:
748        case 0n:
749          Some{v}
750        case 1n+p:
751          at.go(t, p)
752
753# Item n of an array.
754def at(v: Val, n: Nat) -> Maybe<&1, Val>:
755  match v:
756    case Arr{xs}:
757      at.go(xs, n)
758    case Null{}:
759      None{}
760    case Flag{on}:
761      None{}
762    case Num{s}:
763      None{}
764    case Str{s}:
765      None{}
766    case Obj{kvs}:
767      None{}
768
769def u32.over(+acc: U32, +c: U32) -> Bool:
770  Bool.or(U32.is_lt(429496729, acc), Bool.and(U32.is_eq(acc, 429496729), U32.is_lt(53, c)))
771
772def u32.dig(s: String, +acc: U32, bad: Bool) -> Maybe<&2, U32>:
773  match s:
774    case SNil{}:
775      match bad:
776        case True{}:
777          None{}
778        case False{}:
779          Some{acc}
780    case SCon{Chr{+c}, t}:
781      u32.dig(t, (acc * 10 + (c - 48 : U32) : U32), Bool.or(bad, Bool.or(Bool.not(digit(c)), u32.over(acc, c))))
782
783def u32.zero(t: String) -> Maybe<&2, U32>:
784  match t:
785    case SNil{}:
786      Some{0}
787    case SCon{d, u}:
788      None{}
789
790def u32.lead(+c: U32, t: String, zero: Bool) -> Maybe<&2, U32>:
791  match zero:
792    case True{}:
793      u32.zero(t)
794    case False{}:
795      u32.dig(t, (c - 48 : U32), Bool.or(Bool.not(digit(c)), u32.over(0, c)))
796
797def u32.num(s: String) -> Maybe<&2, U32>:
798  match s:
799    case SNil{}:
800      None{}
801    case SCon{Chr{+c}, t}:
802      u32.lead(c, t, U32.is_eq(c, 48))
803
804# A number that is a whole U32, with no sign, fraction or exponent.
805def u32(v: Val) -> Maybe<&2, U32>:
806  match v:
807    case Num{s}:
808      u32.num(Bytes.to_string(s))
809    case Null{}:
810      None{}
811    case Flag{on}:
812      None{}
813    case Str{s}:
814      None{}
815    case Arr{xs}:
816      None{}
817    case Obj{kvs}:
818      None{}
819
820# Encode
821# ------
822
823def w.ctl(ctl: Bool, +c: U32, o: W) -> W:
824  match ctl:
825    case True{}:
826      w.put(w.put(w.put(w.put(w.put(w.put(o, 92), 117), 48), 48), w.hex(U32.shrn(c, 4n))), w.hex((c .&. 15 : U32)))
827    case False{}:
828      w.put(o, c)
829
830# §7: quote, backslash and control chars are escaped. Other bytes are already UTF-8.
831def w.esc.c(+c: U32, o: W) -> W:
832  match c:
833    case 34:
834      w.put(w.put(o, 92), 34)
835    case 92:
836      w.put(w.put(o, 92), 92)
837    case 10:
838      w.put(w.put(o, 92), 110)
839    case 13:
840      w.put(w.put(o, 92), 114)
841    case 9:
842      w.put(w.put(o, 92), 116)
843    case _:
844      w.ctl(U32.is_lt(c, 32), c, o)
845
846def w.bytes.go(n: Nat, r: Array<U32> & U32, +i: U32, o: W) -> W:
847  match n:
848    case 0n:
849      o
850    case 1n+k:
851      (a, +c) = r
852      w.bytes.go(k, Bytes.peek(a, (i + 1 : U32)), (i + 1 : U32), w.put(o, c))
853
854def w.bytes(b: Bytes.Bytes, o: W) -> W:
855  Bytes.Bytes{+len, buf} = b
856  w.bytes.go(U32.to_nat(len), Bytes.peek(buf, 0), 0, o)
857
858def w.str.go(n: Nat, r: Array<U32> & U32, +i: U32, o: W) -> W:
859  match n:
860    case 0n:
861      w.put(o, 34)
862    case 1n+k:
863      (a, +c) = r
864      w.str.go(k, Bytes.peek(a, (i + 1 : U32)), (i + 1 : U32), w.esc.c(c, o))
865
866# A quoted, escaped string.
867def w.str(b: Bytes.Bytes, o: W) -> W:
868  Bytes.Bytes{+len, buf} = b
869  w.str.go(U32.to_nat(len), Bytes.peek(buf, 0), 0, w.put(o, 34))
870
871type Item is Type:
872  ILit{s: String}
873  IKey{k: Bytes.Bytes}
874  IVal{v: Val}
875
876def items.sep(first: Bool, tail: List<&1, Item>) -> List<&1, Item>:
877  match first:
878    case True{}:
879      tail
880    case False{}:
881      Con{ILit{","}, tail}
882
883def items.arr(xs: List<&1, Val>, first: Bool, rest: List<&1, Item>) -> List<&1, Item>:
884  match xs:
885    case Nil{}:
886      Con{ILit{"]"}, rest}
887    case Con{x, t}:
888      items.sep(first, Con{IVal{x}, items.arr(t, False{}, rest)})
889
890def items.obj(kvs: List<&1, Bytes.Bytes & Val>, first: Bool, rest: List<&1, Item>) -> List<&1, Item>:
891  match kvs:
892    case Nil{}:
893      Con{ILit{"}"}, rest}
894    case (k, v) <> t:
895      items.sep(first, Con{IKey{k}, Con{IVal{v}, items.obj(t, False{}, rest)}})
896
897# ponytail: @unsafe because it walks a work list, not the Val; each step
898# emits text or swaps a container for its strictly smaller parts.
899@unsafe
900def encb.go(items: List<&1, Item>, o: W) -> W:
901  match items:
902    case Nil{}:
903      o
904    case Con{ILit{s}, t}:
905      encb.go(t, w.text(s, o))
906    case Con{IKey{k}, t}:
907      encb.go(t, w.put(w.str(k, o), 58))
908    case Con{IVal{Null{}}, t}:
909      encb.go(t, w.text("null", o))
910    case Con{IVal{Flag{True{}}}, t}:
911      encb.go(t, w.text("true", o))
912    case Con{IVal{Flag{False{}}}, t}:
913      encb.go(t, w.text("false", o))
914    case Con{IVal{Num{n}}, t}:
915      encb.go(t, w.bytes(n, o))
916    case Con{IVal{Str{s}}, t}:
917      encb.go(t, w.str(s, o))
918    case Con{IVal{Arr{xs}}, t}:
919      encb.go(Con{ILit{"["}, items.arr(xs, True{}, t)}, o)
920    case Con{IVal{Obj{kvs}}, t}:
921      encb.go(Con{ILit{"{"}, items.obj(kvs, True{}, t)}, o)
922
923# Compact JSON in UTF-8, with object fields in their order.
924def encode.bytes(v: Val) -> Bytes.Bytes:
925  w.done(encb.go(Con{IVal{v}, Nil{}}, W{Bytes.alloc(64), 16, 0, 0}))