@amritk/nish-x86_64-linux 0.18.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/INSTALL.md +58 -28
  2. package/bin/nish +0 -0
  3. package/docs/AI.md +2759 -0
  4. package/package.json +3 -2
  5. package/runtime/browser.d.ts +14 -0
  6. package/runtime/browser.mjs +88 -0
  7. package/runtime/core/arrays.d.ts +18 -0
  8. package/runtime/core/arrays.mjs +125 -0
  9. package/runtime/core/checks.mjs +20 -0
  10. package/runtime/core/host.d.ts +70 -0
  11. package/runtime/core/host.mjs +311 -0
  12. package/runtime/core/numbers.d.ts +53 -0
  13. package/runtime/core/numbers.mjs +316 -0
  14. package/runtime/core/result.d.ts +41 -0
  15. package/runtime/core/result.mjs +127 -0
  16. package/runtime/core/strings.d.ts +14 -0
  17. package/runtime/core/strings.mjs +169 -0
  18. package/runtime/core.d.ts +9 -0
  19. package/runtime/core.mjs +55 -0
  20. package/runtime/host.d.ts +6 -0
  21. package/runtime/nish.d.ts +99 -5
  22. package/runtime/nish.h +289 -19
  23. package/runtime/nish.mjs +39 -3
  24. package/runtime/node.mjs +383 -0
  25. package/runtime/runtime-aes.c +490 -0
  26. package/runtime/runtime-bytes.c +401 -0
  27. package/runtime/runtime-cross.c +366 -0
  28. package/runtime/runtime-host.c +8 -7
  29. package/runtime/runtime-net.c +93 -34
  30. package/runtime/runtime-os.c +214 -16
  31. package/runtime/runtime-parallel.c +590 -107
  32. package/runtime/runtime-simd.c +235 -11
  33. package/runtime/runtime-term.c +504 -0
  34. package/runtime/runtime-wasm.c +5 -14
  35. package/runtime/runtime.c +257 -17
  36. package/runtime/shim.mjs +6 -915
  37. package/runtime/sqlite/LICENSE.md +85 -0
  38. package/runtime/sqlite/README.md +45 -0
  39. package/runtime/sqlite/nish-sqlite.c +359 -0
  40. package/runtime/sqlite/sqlite3.c +271131 -0
  41. package/runtime/sqlite/sqlite3.h +14447 -0
  42. package/scripts/build.sh +437 -28
  43. package/std/LICENSE-fast-float +23 -0
  44. package/std/LICENSE-fdlibm +8 -0
  45. package/std/README.md +108 -58
  46. package/std/base64.ts +116 -0
  47. package/std/bytes.ts +419 -0
  48. package/std/cli.ts +328 -0
  49. package/std/collections.ts +6 -5
  50. package/std/crypto/LICENSE-crypt_blowfish +26 -0
  51. package/std/crypto/LICENSE-libsecp256k1 +19 -0
  52. package/std/crypto/aes.ts +238 -76
  53. package/std/crypto/base64url.ts +125 -0
  54. package/std/crypto/bcrypt.ts +760 -0
  55. package/std/crypto/chacha20poly1305.ts +43 -9
  56. package/std/crypto/ed25519.ts +840 -0
  57. package/std/crypto/hkdf.ts +304 -12
  58. package/std/crypto/hmac.ts +382 -54
  59. package/std/crypto/p256.ts +932 -61
  60. package/std/crypto/x25519.ts +55 -37
  61. package/std/crypto/x509-random.ts +71 -0
  62. package/std/crypto/x509.ts +20 -131
  63. package/std/json-tokenizer.ts +4237 -0
  64. package/std/json-typed.ts +1014 -0
  65. package/std/json-value.ts +1182 -0
  66. package/std/json.ts +1202 -34
  67. package/std/math.ts +608 -0
  68. package/std/net/buffer-pool.ts +151 -0
  69. package/std/net/hpack.ts +416 -112
  70. package/std/net/http-fields.ts +93 -0
  71. package/std/net/http1-server.ts +501 -62
  72. package/std/net/http1.ts +31 -6
  73. package/std/net/http2-tls.ts +112 -24
  74. package/std/net/http2.ts +333 -75
  75. package/std/net/http3-server.ts +261 -43
  76. package/std/net/http3.ts +187 -28
  77. package/std/net/postgres.ts +1875 -0
  78. package/std/net/prefork.ts +412 -0
  79. package/std/net/quic-listener.ts +108 -11
  80. package/std/net/quic-packet.ts +243 -82
  81. package/std/net/quic-recovery.ts +361 -30
  82. package/std/net/quic-stream.ts +424 -24
  83. package/std/net/quic.ts +519 -167
  84. package/std/net/router.ts +676 -0
  85. package/std/net/tls/codec.ts +426 -27
  86. package/std/net/tls/record-server.ts +478 -132
  87. package/std/net/tls/record.ts +133 -42
  88. package/std/net/tls/schedule.ts +464 -55
  89. package/std/net/tls/ticket.ts +610 -0
  90. package/std/net/tls-tcp.ts +196 -53
  91. package/std/net/tls.ts +1018 -260
  92. package/std/net/url.ts +571 -0
  93. package/std/random.ts +94 -0
  94. package/std/regex.ts +4274 -0
  95. package/std/sqlite.ts +391 -0
  96. package/std/term-io.ts +978 -0
  97. package/std/term-pixels.ts +874 -0
  98. package/std/term-probe.ts +459 -0
  99. package/std/term-rate.ts +993 -0
  100. package/std/term.ts +2453 -0
  101. package/std/text.ts +90 -7
  102. package/std/threads.ts +438 -14
  103. package/std/yaml-lines.ts +141 -0
  104. package/std/yaml.ts +4675 -0
@@ -0,0 +1,1182 @@
1
+ /**
2
+ * `nish/json-value` — any JSON document as a tree a program can read, build
3
+ * and write back, with every number kept as the text it was written in.
4
+ *
5
+ * `nish/json-typed` reads JSON into a class the program declares, which is the
6
+ * fast and safe way when the shape is known. This module is for when it is
7
+ * not: a configuration file, a proxy that rewrites one field and passes the
8
+ * rest through, a tool that prints whatever it was given.
9
+ *
10
+ * import { JsonDocument, JSON_VALUE_NUMBER } from "nish/json-value"
11
+ * import { JsonLimits } from "nish/json-tokenizer"
12
+ *
13
+ * const doc = new JsonDocument(new JsonLimits())
14
+ * const root = doc.parseText('{"id":18446744073709551615,"tags":["a","b"]}')
15
+ * if (root < 0) {
16
+ * // a JSON_TOK_ERR_* code, or JSON_VALUE_ERR_DUPLICATE; the byte is doc.errorAt
17
+ * }
18
+ * const id = doc.get(root, "id")
19
+ * doc.kind(id) === JSON_VALUE_NUMBER // true
20
+ * doc.isU64(id) // true; doc.isI64(id) is false
21
+ * doc.numberText(id) // "18446744073709551615", as written
22
+ * doc.stringify(root) // the same text back, byte for byte
23
+ *
24
+ * **A value is a handle.** `JsonValue` is an `i32` naming one value of the
25
+ * document that made it, and every reader and builder is a method of that
26
+ * document. A handle stays valid until the document parses again or is
27
+ * `clear`ed, which forgets every value at once and keeps the memory: the
28
+ * nodes, the member slots and the bytes of every string and number live in a
29
+ * handful of arrays the document owns and reuses. A server keeps one document
30
+ * and parses each request into it, and once the arrays have grown to the
31
+ * largest request seen, parsing allocates nothing.
32
+ *
33
+ * A handle carries the generation of the document's contents it was made in,
34
+ * which moves on at every `parse` and `clear`, so a handle kept from an
35
+ * earlier request names nothing in the next one, even when the next one has
36
+ * the same shape: it is `JSON_VALUE_NONE` to `kind`, and every reader answers
37
+ * its empty value for it rather than another document's. The generation has
38
+ * 511 values and moves by one at a `clear`, one at a parse and two at a parse
39
+ * that fails, so the check misses only a handle kept across exactly a
40
+ * multiple of 511 of those steps; a program must not keep handles across
41
+ * documents, and this catches the mistake rather than licensing it. A
42
+ * negative handle, or one past the last value, is `JSON_VALUE_NONE` too.
43
+ *
44
+ * **The document's size is bounded.** Each value costs about 46 bytes of the
45
+ * arrays the document keeps for its life, on top of the decoded text of its
46
+ * strings, keys and numbers, which `JsonLimits.maxTotalBytes` bounds through
47
+ * the input (`docs/security/json.md`, JSON-10). `maxValues` caps the first
48
+ * part by capping how many values one document holds:
49
+ * `JSON_VALUE_DEFAULT_MAX_VALUES` unless the program sets it, at most
50
+ * `JSON_VALUE_MAX_VALUES`. A parse that would make one more is
51
+ * `JSON_VALUE_ERR_VALUES` at the byte of the value that does not fit, and a
52
+ * builder answers the same code.
53
+ *
54
+ * **Numbers are lossless.** A number keeps its source text, and is read as
55
+ * whatever the caller asks for when it asks: `i64` and `u64` when the text is
56
+ * an integer that fits (`isI64`, `isU64`), whether its value is whole at all
57
+ * (`isIntegral`, so `1.0` and `1e2` are), the nearest `f64` (`f64`, correctly
58
+ * rounded, the tokenizer's `numberF64`), or the text itself (`numberText`).
59
+ * Writing it back copies the text. So `18446744073709551616`, wider than any
60
+ * integer type, and `0.1000000000000000055511151231257827`, more digits than an
61
+ * `f64` holds, come back out exactly as they went in, where JavaScript's
62
+ * `JSON.parse` turns both into the nearest double.
63
+ *
64
+ * **Objects keep insertion order**, the order the members were written in or
65
+ * added. `get` finds a member by its key with a scan, so it is for a handful of
66
+ * lookups per object; a program that looks up many keys of a large object
67
+ * walks it once with `keyAt` and `at`.
68
+ *
69
+ * **Duplicate keys are refused by default.** `{"a":1,"a":2}` is
70
+ * `JSON_VALUE_ERR_DUPLICATE`, with `errorAt` at the first key that repeats an
71
+ * earlier one, because two readers that pick different members of the same
72
+ * text are a check bypassed (`docs/security/json.md`, JSON-3), and refusing
73
+ * is what `nish/json-typed` does too. A program that has to accept what
74
+ * `JSON.parse` accepts sets `duplicates` to `JSON_VALUE_DUPLICATE_LAST`, and
75
+ * gets `JSON.parse`'s answer: one member, at the place of the first, holding
76
+ * the value of the last. The check sorts each object's keys, so an object of
77
+ * n members costs n log n comparisons whatever the keys are.
78
+ *
79
+ * **Every limit and every parse error is the tokenizer's.** `parse` runs a
80
+ * `JsonTokenizer` with the `JsonLimits` the document was made with, and
81
+ * answers its `JSON_TOK_ERR_*` code and offset unchanged. The depth limit is
82
+ * capped at `JSON_WRITER_MAX_DEPTH`, 64, so that every document a parse
83
+ * accepts can be written back; a deeper one is the tokenizer's
84
+ * `JSON_TOK_ERR_DEPTH`. Nothing an input holds panics, and the parse keeps its
85
+ * own stack of open containers rather than recursing.
86
+ *
87
+ * **Writing goes through `JsonWriter`.** `write(v, w)` writes a value into a
88
+ * writer the caller set up, so its buffer, its reuse and its sticky
89
+ * `JSON_WRITE_*` codes are the writer's own, and `stringify` is a convenience
90
+ * that sizes a buffer and answers a string. Strings come out as `JsonWriter`
91
+ * escapes them, which is `JSON.stringify`'s rule, numbers as their text, and
92
+ * members in order. Only a built tree can be deeper than
93
+ * `JSON_WRITER_MAX_DEPTH`, and writing one is the writer's
94
+ * `JSON_WRITE_TOO_DEEP`.
95
+ *
96
+ * **Building a tree** is a `new*` call per value, then `push` onto an array or
97
+ * `set` on an object, each answering `JSON_VALUE_OK` or a negative code. A
98
+ * value lives in at most one container, so a tree built through `push` and
99
+ * `set` can never contain itself: adding a value that is already in a
100
+ * container, or a container to itself or to anything inside it, is
101
+ * `JSON_VALUE_ERR_ATTACHED`, and writing always ends.
102
+ * Strings handed to a builder are taken as their bytes, as `JsonWriter` takes
103
+ * them, and a string read back is made from the stored bytes in one
104
+ * allocation (`String.fromBytes`). Under Node a string is UTF-16, and
105
+ * `parseText` and the builders take one byte per code unit, so non-ASCII text
106
+ * is stored differently there than natively, where a string is its UTF-8
107
+ * bytes; `parse` over a `u8[]` reads the same bytes both ways.
108
+ *
109
+ * **Public is not the whole API.** Nish has no private members, so the
110
+ * methods marked "Internal" in their comments, and the fields, are reachable
111
+ * by a program; the guarantees above hold only through the methods that are
112
+ * not marked so. `append` with indices of the program's choosing, for
113
+ * example, skips the check that keeps a tree finite.
114
+ *
115
+ * Every name here is `json`-prefixed, because a `std/` module is compiled into
116
+ * the program that imports it and the symbol namespace is flat
117
+ * (`std/README.md`). Every offset, count and code is an `i32`, so the module is
118
+ * the same under `--number-mode f64`, and it runs under the Node prelude, where
119
+ * `tests/run.js` holds every method to the native answers.
120
+ */
121
+ import { JSON_WRITE_FULL, JSON_WRITE_OK, JSON_WRITER_MAX_DEPTH, JsonWriter } from "nish/json"
122
+ import {
123
+ JSON_TOK_ARRAY_BEGIN,
124
+ JSON_TOK_ARRAY_END,
125
+ JSON_TOK_END,
126
+ JSON_TOK_KEY,
127
+ JSON_TOK_NULL,
128
+ JSON_TOK_NUMBER,
129
+ JSON_TOK_OBJECT_BEGIN,
130
+ JSON_TOK_OBJECT_END,
131
+ JSON_TOK_STRING,
132
+ JSON_TOK_TRUE,
133
+ JsonLimits,
134
+ JsonTokenizer,
135
+ } from "nish/json-tokenizer"
136
+
137
+ /** A value in a `JsonDocument`: an index into it, valid until the document parses again or is cleared. */
138
+ export type JsonValue = i32
139
+
140
+ /** What `kind` answers for a handle that names no value. */
141
+ export const JSON_VALUE_NONE: i32 = 0
142
+ export const JSON_VALUE_NULL: i32 = 1
143
+ export const JSON_VALUE_BOOLEAN: i32 = 2
144
+ /** A number, kept as its text: `numberText`, `isI64`, `i64`, `isU64`, `u64` and `f64` read it. */
145
+ export const JSON_VALUE_NUMBER: i32 = 3
146
+ export const JSON_VALUE_STRING: i32 = 4
147
+ export const JSON_VALUE_ARRAY: i32 = 5
148
+ export const JSON_VALUE_OBJECT: i32 = 6
149
+
150
+ /** What a builder answers when it did what it was asked. */
151
+ export const JSON_VALUE_OK: i32 = 0
152
+ /** A key an object already has, refused while `duplicates` is `JSON_VALUE_DUPLICATE_REFUSE`. */
153
+ export const JSON_VALUE_ERR_DUPLICATE: i32 = -30
154
+ /** A handle that names no value, or a value of the wrong kind: `push` onto an object, `set` on an array. */
155
+ export const JSON_VALUE_ERR_HANDLE: i32 = -31
156
+ /** A value already in a container, or a container added to itself or to a value inside it. */
157
+ export const JSON_VALUE_ERR_ATTACHED: i32 = -32
158
+ /** Text that is not one JSON number, for `newNumber`, or an `f64` that is NaN or an infinity, for `newF64`. */
159
+ export const JSON_VALUE_ERR_NUMBER: i32 = -33
160
+ /** One value more than `JsonDocument.maxValues`, by a parse (with `errorAt` at its first byte) or a builder. */
161
+ export const JSON_VALUE_ERR_VALUES: i32 = -34
162
+
163
+ /**
164
+ * The most values one document holds by default: a parse that would make
165
+ * more is `JSON_VALUE_ERR_VALUES`. Each value costs the document about 46
166
+ * bytes of arrays it keeps (`docs/security/json.md`, JSON-10), so this caps
167
+ * them near 12 MB; a program raises `maxValues` up to
168
+ * `JSON_VALUE_MAX_VALUES` for larger documents.
169
+ */
170
+ export const JSON_VALUE_DEFAULT_MAX_VALUES: i32 = 262144
171
+ /** The most `maxValues` can be: a handle keeps a value's index in its low 22 bits. */
172
+ export const JSON_VALUE_MAX_VALUES: i32 = 4194304
173
+
174
+ /** The default: a repeated key is `JSON_VALUE_ERR_DUPLICATE`. */
175
+ export const JSON_VALUE_DUPLICATE_REFUSE: i32 = 0
176
+ /** `JSON.parse`'s rule: one member, at the first key's place, with the last key's value. */
177
+ export const JSON_VALUE_DUPLICATE_LAST: i32 = 1
178
+
179
+ /**
180
+ * A handle is `generation << JSON_VALUE_INDEX_BITS | index`. The generation
181
+ * runs from 1 to `JSON_VALUE_LAST_GENERATION` and moves on by one at every
182
+ * `clear` and every parse, two at a parse that fails, so a handle kept from an
183
+ * earlier document names nothing in this one, unless exactly a multiple of
184
+ * 511 of those steps have passed.
185
+ */
186
+ const JSON_VALUE_INDEX_BITS: i32 = 22
187
+ const JSON_VALUE_INDEX_MASK: i32 = 4194303
188
+ const JSON_VALUE_LAST_GENERATION: i32 = 511
189
+ /** At most this many members are checked for duplicates pair by pair; a larger object is sorted. */
190
+ const JSON_VALUE_PAIRWISE: i32 = 8
191
+ /** How many member slots a built container gets when it first grows. */
192
+ const JSON_VALUE_FIRST_SLOTS: i32 = 4
193
+ /** The largest an `i32` count may be, which every limit of the number reader is set to. */
194
+ const JSON_VALUE_I32_MAX: i32 = 2147483647
195
+ const JSON_VALUE_DIGIT_0: i32 = 48
196
+ /** The words of a value with nothing to point at, and a `true` boolean's first word; spelled `i32` for `--number-mode f64`. */
197
+ const JSON_VALUE_NO_WORD: i32 = 0
198
+ const JSON_VALUE_TRUE_WORD: i32 = 1
199
+ const JSON_VALUE_MINUS: i32 = 45
200
+
201
+ /**
202
+ * A JSON tree, and the memory every value of it lives in. Make one, then
203
+ * `parse` into it or build with the `new*` methods; the module header has the
204
+ * rules. Its fields and its "Internal" methods are reachable, as every
205
+ * member in Nish is; use the others.
206
+ */
207
+ export class JsonDocument {
208
+ /** Per value: its `JSON_VALUE_*` kind. */
209
+ kinds: u8[]
210
+ /** Per value: a string's or a number's first byte in `bytes`, a container's first slot, a boolean's `0` or `1`. */
211
+ first: i32[]
212
+ /** Per value: a string's or a number's byte count, or a container's member count. */
213
+ count: i32[]
214
+ /** Per value: how many slots a container has from `first`, its members and room to grow. */
215
+ room: i32[]
216
+ /** Per value: the container it is in, or `-1`. */
217
+ parent: i32[]
218
+ /** Per member slot: the member's value, and an object member's key as a window of `bytes`. */
219
+ slotValue: i32[]
220
+ slotKeyAt: i32[]
221
+ slotKeyLength: i32[]
222
+ /** The bytes of every string, key and number, decoded, one after the other. */
223
+ bytes: u8[]
224
+ /**
225
+ * The parse's own stacks: the open containers, where each one's members
226
+ * start in the pending arrays and the key it is the value of, if any; and
227
+ * the pending arrays, which hold every member read and not yet
228
+ * placed, with its key and the key's source offset. The sort arrays are the
229
+ * duplicate check's. All of them keep their length from one parse to the
230
+ * next, which is what lets a parse allocate nothing.
231
+ */
232
+ openValue: i32[]
233
+ openBase: i32[]
234
+ openKeyAt: i32[]
235
+ openKeyLength: i32[]
236
+ openKeySource: i32[]
237
+ pendingValue: i32[]
238
+ pendingKeyAt: i32[]
239
+ pendingKeyLength: i32[]
240
+ pendingSource: i32[]
241
+ sortA: i32[]
242
+ sortB: i32[]
243
+ /** `parseText`'s copy of its string. */
244
+ textBytes: u8[]
245
+ tok: JsonTokenizer
246
+ /** A tokenizer over one stored number at a time, for `isI64`, `i64` and `f64`, limited only by `i32`. */
247
+ numbers: JsonTokenizer
248
+
249
+ /** `JSON_VALUE_DUPLICATE_REFUSE` or `JSON_VALUE_DUPLICATE_LAST`; read by `parse`. */
250
+ duplicates: i32 = 0
251
+ /** The last `parse`'s code: `0`, a `JSON_TOK_ERR_*` code or `JSON_VALUE_ERR_DUPLICATE`. */
252
+ failed: i32 = 0
253
+ /** The byte offset in the parsed array the error was found at, and `-1` until one. */
254
+ errorAt: i32 = -1
255
+ /** How many values are in use: the handles are `0 .. top - 1`. */
256
+ top: i32 = 0
257
+ /** How many member slots are in use, and how many bytes. */
258
+ slotTop: i32 = 0
259
+ byteTop: i32 = 0
260
+ /** How many members are pending. */
261
+ pendingTop: i32 = 0
262
+ /** The most values the document holds; more is `JSON_VALUE_ERR_VALUES`. At most `JSON_VALUE_MAX_VALUES`. */
263
+ maxValues: i32 = 0
264
+ /** The generation every handle of the current document carries; see `JSON_VALUE_INDEX_BITS`. */
265
+ generation: i32 = 1
266
+ /** Whether the last `unsigned` read a number that fits a `u64`. */
267
+ unsignedFits: boolean = false
268
+
269
+ constructor(limits: JsonLimits) {
270
+ this.maxValues = JSON_VALUE_DEFAULT_MAX_VALUES
271
+ this.kinds = []
272
+ this.first = []
273
+ this.count = []
274
+ this.room = []
275
+ this.parent = []
276
+ this.slotValue = []
277
+ this.slotKeyAt = []
278
+ this.slotKeyLength = []
279
+ this.bytes = []
280
+ this.openValue = []
281
+ this.openBase = []
282
+ this.openKeyAt = []
283
+ this.openKeyLength = []
284
+ this.openKeySource = []
285
+ this.pendingValue = []
286
+ this.pendingKeyAt = []
287
+ this.pendingKeyLength = []
288
+ this.pendingSource = []
289
+ this.sortA = []
290
+ this.sortB = []
291
+ this.textBytes = []
292
+ // The writer nests 64 deep, so a parsed document is held to that too:
293
+ // every document a parse accepts can be written back.
294
+ const capped = new JsonLimits()
295
+ capped.maxDepth = limits.maxDepth < JSON_WRITER_MAX_DEPTH ? limits.maxDepth : JSON_WRITER_MAX_DEPTH
296
+ capped.maxStringBytes = limits.maxStringBytes
297
+ capped.maxNumberBytes = limits.maxNumberBytes
298
+ capped.maxTotalBytes = limits.maxTotalBytes
299
+ this.tok = new JsonTokenizer(this.bytes, 0, 0, capped)
300
+ const wide = new JsonLimits()
301
+ wide.maxDepth = 0
302
+ wide.maxNumberBytes = JSON_VALUE_I32_MAX
303
+ wide.maxTotalBytes = JSON_VALUE_I32_MAX
304
+ this.numbers = new JsonTokenizer(this.bytes, 0, 0, wide)
305
+ }
306
+
307
+ /** Forgets every value, keeping the memory for the next parse or build. Every handle is invalid afterwards. */
308
+ clear(): void {
309
+ this.generation = this.generation >= JSON_VALUE_LAST_GENERATION ? 1 : this.generation + 1
310
+ this.top = 0
311
+ this.slotTop = 0
312
+ this.byteTop = 0
313
+ this.pendingTop = 0
314
+ this.failed = 0
315
+ this.errorAt = -1
316
+ }
317
+
318
+ // ---- Parsing ----------------------------------------------------------------
319
+
320
+ /**
321
+ * Clears the document and parses `src[off, off + len)` into it. Answers the
322
+ * root value, or a negative code — the tokenizer's `JSON_TOK_ERR_*` or
323
+ * `JSON_VALUE_ERR_DUPLICATE` — which is also in `failed`, with the byte
324
+ * offset in `errorAt`. Nothing is kept from a parse that fails.
325
+ */
326
+ parse(src: u8[], off: i32, len: i32): JsonValue {
327
+ this.clear()
328
+ const tok: JsonTokenizer = this.tok
329
+ tok.reset(src, off, len)
330
+ let depth: i32 = 0
331
+ let root: i32 = -1
332
+ let keyAt: i32 = 0
333
+ let keyLength: i32 = 0
334
+ let keySource: i32 = 0
335
+ let k: i32 = tok.next()
336
+ while (k > 0) {
337
+ let v: i32 = -1
338
+ if (k === JSON_TOK_KEY) {
339
+ keySource = tok.tokStart
340
+ keyAt = this.byteTop
341
+ keyLength = this.storeString(tok)
342
+ } else if (k === JSON_TOK_OBJECT_BEGIN || k === JSON_TOK_ARRAY_BEGIN) {
343
+ const c: i32 = this.newNode(
344
+ k === JSON_TOK_OBJECT_BEGIN ? JSON_VALUE_OBJECT : JSON_VALUE_ARRAY,
345
+ JSON_VALUE_NO_WORD,
346
+ JSON_VALUE_NO_WORD
347
+ )
348
+ if (c < 0) {
349
+ return this.parseFailed(c, tok.tokStart)
350
+ }
351
+ jsonValuePut(this.openValue, depth, c)
352
+ jsonValuePut(this.openBase, depth, this.pendingTop)
353
+ jsonValuePut(this.openKeyAt, depth, keyAt)
354
+ jsonValuePut(this.openKeyLength, depth, keyLength)
355
+ jsonValuePut(this.openKeySource, depth, keySource)
356
+ depth += 1
357
+ } else if (k === JSON_TOK_OBJECT_END || k === JSON_TOK_ARRAY_END) {
358
+ depth -= 1
359
+ const c: i32 = jsonValueGet(this.openValue, depth)
360
+ const code: i32 = this.close(c, jsonValueGet(this.openBase, depth))
361
+ if (code < 0) {
362
+ return this.parseFailed(code, this.errorAt)
363
+ }
364
+ // The container's own key, read before its members' keys overwrote the three locals.
365
+ keyAt = jsonValueGet(this.openKeyAt, depth)
366
+ keyLength = jsonValueGet(this.openKeyLength, depth)
367
+ keySource = jsonValueGet(this.openKeySource, depth)
368
+ v = c
369
+ } else if (k === JSON_TOK_STRING) {
370
+ v = this.newNode(JSON_VALUE_STRING, this.byteTop, this.storeString(tok))
371
+ } else if (k === JSON_TOK_NUMBER) {
372
+ v = this.newNode(JSON_VALUE_NUMBER, this.byteTop, this.storeSource(tok))
373
+ } else if (k === JSON_TOK_NULL) {
374
+ v = this.newNode(JSON_VALUE_NULL, JSON_VALUE_NO_WORD, JSON_VALUE_NO_WORD)
375
+ } else {
376
+ v = this.newNode(
377
+ JSON_VALUE_BOOLEAN,
378
+ k === JSON_TOK_TRUE ? JSON_VALUE_TRUE_WORD : JSON_VALUE_NO_WORD,
379
+ JSON_VALUE_NO_WORD
380
+ )
381
+ }
382
+ // `-1` is a key or an opener, which place no value yet; below it, the value was refused.
383
+ if (v < -1) {
384
+ return this.parseFailed(v, tok.tokStart)
385
+ }
386
+ if (v >= 0) {
387
+ if (depth === 0) {
388
+ root = v
389
+ } else {
390
+ const p: i32 = this.pendingTop
391
+ jsonValuePut(this.pendingValue, p, v)
392
+ jsonValuePut(this.pendingKeyAt, p, keyAt)
393
+ jsonValuePut(this.pendingKeyLength, p, keyLength)
394
+ jsonValuePut(this.pendingSource, p, keySource)
395
+ this.pendingTop = p + 1
396
+ }
397
+ }
398
+ k = tok.next()
399
+ }
400
+ if (k < 0 || root < 0) {
401
+ return this.parseFailed(k < 0 ? k : JSON_VALUE_ERR_HANDLE, tok.errorAt)
402
+ }
403
+ return this.handle(root)
404
+ }
405
+
406
+ /** `parse` over the bytes of `s`, copied into an array the document reuses; `errorAt` is a byte offset in `s`. */
407
+ parseText(s: string): JsonValue {
408
+ const n: i32 = toI32(s.length)
409
+ const buf: u8[] = jsonValueRoom(this.textBytes, n)
410
+ this.textBytes = buf
411
+ for (let i: i32 = 0; i < n && i < toI32(buf.length); i += 1) {
412
+ buf[i] = toU8(s.charCodeAt(i))
413
+ }
414
+ return this.parse(buf, JSON_VALUE_NO_WORD, n)
415
+ }
416
+
417
+ /** Internal: Records a failed parse and forgets what it built. */
418
+ parseFailed(code: i32, at: i32): i32 {
419
+ this.clear()
420
+ this.failed = code
421
+ this.errorAt = at
422
+ return code
423
+ }
424
+
425
+ /**
426
+ * Internal: Places the members pending from `base` into container `c` as one run of
427
+ * slots, checking an object's keys for duplicates first. Answers `0`, or
428
+ * `JSON_VALUE_ERR_DUPLICATE` with `errorAt` set.
429
+ */
430
+ close(c: i32, base: i32): i32 {
431
+ let n: i32 = this.pendingTop - base
432
+ const object: boolean = this.kindAt(c) === JSON_VALUE_OBJECT
433
+ if (object && n > 1) {
434
+ const code: i32 = this.duplicateKeys(base, n)
435
+ if (code < 0) {
436
+ return code
437
+ }
438
+ }
439
+ const start: i32 = this.slotTop
440
+ let kept: i32 = 0
441
+ for (let p: i32 = base; p < base + n; p += 1) {
442
+ const v: i32 = jsonValueGet(this.pendingValue, p)
443
+ if (v < 0) {
444
+ continue
445
+ }
446
+ const s: i32 = start + kept
447
+ jsonValuePut(this.slotValue, s, v)
448
+ jsonValuePut(this.slotKeyAt, s, jsonValueGet(this.pendingKeyAt, p))
449
+ jsonValuePut(this.slotKeyLength, s, jsonValueGet(this.pendingKeyLength, p))
450
+ jsonValuePut(this.parent, v, c)
451
+ kept += 1
452
+ }
453
+ n = kept
454
+ this.slotTop = start + n
455
+ jsonValuePut(this.first, c, start)
456
+ jsonValuePut(this.count, c, n)
457
+ jsonValuePut(this.room, c, n)
458
+ this.pendingTop = base
459
+ return 0
460
+ }
461
+
462
+ /**
463
+ * Internal: The duplicate check over the `n` members pending from `base`. Under
464
+ * `JSON_VALUE_DUPLICATE_LAST`, a repeated key's later members are marked
465
+ * gone (their pending value set to `-1`) and the first one takes the last
466
+ * one's value. Small objects compare every pair; larger ones are sorted by
467
+ * key with ties in member order, so a key's repeats are next to each other
468
+ * and the first of them is its first member.
469
+ */
470
+ duplicateKeys(base: i32, n: i32): i32 {
471
+ let firstRepeat: i32 = -1
472
+ if (n <= JSON_VALUE_PAIRWISE) {
473
+ for (let i: i32 = base + 1; i < base + n; i += 1) {
474
+ for (let j: i32 = base; j < i; j += 1) {
475
+ if (jsonValueGet(this.pendingValue, j) >= 0 && this.samePendingKey(i, j)) {
476
+ firstRepeat = this.repeat(j, i, firstRepeat)
477
+ break
478
+ }
479
+ }
480
+ }
481
+ } else {
482
+ const order: i32[] = this.sortPending(base, n)
483
+ let i: i32 = 0
484
+ while (i < n) {
485
+ const head: i32 = jsonValueGet(order, i)
486
+ let j: i32 = i + 1
487
+ while (j < n && this.samePendingKey(head, jsonValueGet(order, j))) {
488
+ firstRepeat = this.repeat(head, jsonValueGet(order, j), firstRepeat)
489
+ j += 1
490
+ }
491
+ i = j
492
+ }
493
+ }
494
+ if (firstRepeat >= 0 && this.duplicates !== JSON_VALUE_DUPLICATE_LAST) {
495
+ this.errorAt = firstRepeat
496
+ return JSON_VALUE_ERR_DUPLICATE
497
+ }
498
+ return 0
499
+ }
500
+
501
+ /**
502
+ * Internal: Pending member `later` repeats the key of the earlier `head`: under
503
+ * `JSON_VALUE_DUPLICATE_LAST` `head` takes its value and it is marked gone.
504
+ * Answers the smallest source offset of a repeating key seen so far.
505
+ */
506
+ repeat(head: i32, later: i32, firstRepeat: i32): i32 {
507
+ const source: i32 = jsonValueGet(this.pendingSource, later)
508
+ if (this.duplicates === JSON_VALUE_DUPLICATE_LAST) {
509
+ jsonValuePut(this.pendingValue, head, jsonValueGet(this.pendingValue, later))
510
+ jsonValuePut(this.pendingValue, later, -1)
511
+ }
512
+ return firstRepeat < 0 || source < firstRepeat ? source : firstRepeat
513
+ }
514
+
515
+ /** Internal: Whether pending members `a` and `b` have the same key bytes. */
516
+ samePendingKey(a: i32, b: i32): boolean {
517
+ return this.comparePending(a, b) === 0
518
+ }
519
+
520
+ /**
521
+ * Internal: The pending indices `base .. base + n - 1` sorted by key, ties in index
522
+ * order: a bottom-up merge sort between the two sort arrays, which answers
523
+ * whichever of them holds the result.
524
+ */
525
+ sortPending(base: i32, n: i32): i32[] {
526
+ let from: i32[] = jsonValueRoomI32(this.sortA, n)
527
+ let to: i32[] = jsonValueRoomI32(this.sortB, n)
528
+ this.sortA = from
529
+ this.sortB = to
530
+ for (let i: i32 = 0; i < n && i < toI32(from.length); i += 1) {
531
+ from[i] = base + i
532
+ }
533
+ let width: i32 = 1
534
+ while (width < n) {
535
+ let lo: i32 = 0
536
+ while (lo < n) {
537
+ const mid: i32 = lo + width < n ? lo + width : n
538
+ const hi: i32 = mid + width < n ? mid + width : n
539
+ let a: i32 = lo
540
+ let b: i32 = mid
541
+ let out: i32 = lo
542
+ while (out < hi) {
543
+ const takeA: boolean =
544
+ b >= hi || (a < mid && this.comparePending(jsonValueGet(from, a), jsonValueGet(from, b)) <= 0)
545
+ if (takeA) {
546
+ jsonValuePut(to, out, jsonValueGet(from, a))
547
+ a += 1
548
+ } else {
549
+ jsonValuePut(to, out, jsonValueGet(from, b))
550
+ b += 1
551
+ }
552
+ out += 1
553
+ }
554
+ lo = hi
555
+ }
556
+ const swap: i32[] = from
557
+ from = to
558
+ to = swap
559
+ width = width * 2
560
+ }
561
+ return from
562
+ }
563
+
564
+ /** Internal: Pending members `a` and `b` ordered by key bytes. */
565
+ comparePending(a: i32, b: i32): i32 {
566
+ return jsonValueCompareBytes(
567
+ this.bytes,
568
+ jsonValueGet(this.pendingKeyAt, a),
569
+ jsonValueGet(this.pendingKeyLength, a),
570
+ jsonValueGet(this.pendingKeyAt, b),
571
+ jsonValueGet(this.pendingKeyLength, b)
572
+ )
573
+ }
574
+
575
+ /** Internal: The tokenizer's current string or key, decoded onto the end of `bytes`; answers its length. */
576
+ storeString(tok: JsonTokenizer): i32 {
577
+ const n: i32 = tok.stringLength()
578
+ const at: i32 = this.byteTop
579
+ const buf: u8[] = jsonValueRoom(this.bytes, at + n)
580
+ this.bytes = buf
581
+ tok.stringInto(buf, at)
582
+ this.byteTop = at + n
583
+ return n
584
+ }
585
+
586
+ /** Internal: The tokenizer's current token as written, a number's text, onto the end of `bytes`; answers its length. */
587
+ storeSource(tok: JsonTokenizer): i32 {
588
+ const src: u8[] = tok.src
589
+ const start: i32 = tok.tokStart
590
+ const n: i32 = tok.tokEnd - start
591
+ const at: i32 = this.byteTop
592
+ const buf: u8[] = jsonValueRoom(this.bytes, at + n)
593
+ this.bytes = buf
594
+ for (let i: i32 = 0; i < n && start + i < toI32(src.length) && at + i < toI32(buf.length); i += 1) {
595
+ if (start + i >= 0 && at + i >= 0) {
596
+ buf[at + i] = src[start + i]
597
+ }
598
+ }
599
+ this.byteTop = at + n
600
+ return n
601
+ }
602
+
603
+ /**
604
+ * Internal: a new value of `kind` with its two words, in no container, and
605
+ * its index; `JSON_VALUE_ERR_VALUES` when the document already holds
606
+ * `maxValues`.
607
+ */
608
+ newNode(kind: i32, first: i32, count: i32): i32 {
609
+ const v: i32 = this.top
610
+ const cap: i32 = this.maxValues < JSON_VALUE_MAX_VALUES ? this.maxValues : JSON_VALUE_MAX_VALUES
611
+ if (v >= cap) {
612
+ return JSON_VALUE_ERR_VALUES
613
+ }
614
+ if (v < toI32(this.kinds.length)) {
615
+ this.kinds[v] = toU8(kind)
616
+ } else {
617
+ this.kinds.push(toU8(kind))
618
+ }
619
+ jsonValuePut(this.first, v, first)
620
+ jsonValuePut(this.count, v, count)
621
+ jsonValuePut(this.room, v, 0)
622
+ jsonValuePut(this.parent, v, -1)
623
+ this.top = v + 1
624
+ return v
625
+ }
626
+
627
+ // ---- Handles ----------------------------------------------------------------
628
+
629
+ /** Internal: the index handle `v` names in this document, or `-1` when it names nothing here. */
630
+ index(v: JsonValue): i32 {
631
+ if (v < 0 || v >> JSON_VALUE_INDEX_BITS !== this.generation) {
632
+ return -1
633
+ }
634
+ const x: i32 = v & JSON_VALUE_INDEX_MASK
635
+ return x < this.top ? x : -1
636
+ }
637
+
638
+ /** Internal: the handle of index `x` in this document's generation; a negative `x` is answered as it is. */
639
+ handle(x: i32): JsonValue {
640
+ return x < 0 ? x : (this.generation << JSON_VALUE_INDEX_BITS) | x
641
+ }
642
+
643
+ // ---- Reading ----------------------------------------------------------------
644
+
645
+ /** `v`'s `JSON_VALUE_*` kind, or `JSON_VALUE_NONE` when `v` names no value of this document's current contents. */
646
+ kind(v: JsonValue): i32 {
647
+ return this.kindAt(this.index(v))
648
+ }
649
+
650
+ /** Internal: the kind of index `x`, or `JSON_VALUE_NONE`. */
651
+ kindAt(x: i32): i32 {
652
+ const kinds: u8[] = this.kinds
653
+ if (x < 0 || x >= this.top || x >= toI32(kinds.length)) {
654
+ return JSON_VALUE_NONE
655
+ }
656
+ return toI32(kinds[x])
657
+ }
658
+
659
+ /** A boolean's value; `false` for any other value. */
660
+ boolean(v: JsonValue): boolean {
661
+ const x: i32 = this.index(v)
662
+ return this.kindAt(x) === JSON_VALUE_BOOLEAN && jsonValueGet(this.first, x) === JSON_VALUE_TRUE_WORD
663
+ }
664
+
665
+ /** How many elements an array has, or members an object has; `-1` for any other value. */
666
+ length(v: JsonValue): i32 {
667
+ return this.lengthAt(this.index(v))
668
+ }
669
+
670
+ /** Internal: `length` of index `x`. */
671
+ lengthAt(x: i32): i32 {
672
+ const k: i32 = this.kindAt(x)
673
+ return k === JSON_VALUE_ARRAY || k === JSON_VALUE_OBJECT ? jsonValueGet(this.count, x) : -1
674
+ }
675
+
676
+ /** Internal: the slot of member or element `i` of the container at index `x`, or `-1`. */
677
+ slotAt(x: i32, i: i32): i32 {
678
+ if (i < 0 || i >= this.lengthAt(x)) {
679
+ return -1
680
+ }
681
+ return jsonValueGet(this.first, x) + i
682
+ }
683
+
684
+ /** Element `i` of an array, or the value of member `i` of an object, in order; `-1` when there is none. */
685
+ at(v: JsonValue, i: i32): JsonValue {
686
+ const s: i32 = this.slotAt(this.index(v), i)
687
+ return s < 0 ? -1 : this.handle(jsonValueGet(this.slotValue, s))
688
+ }
689
+
690
+ /** The key of member `i` of an object, decoded; `""` when `v` is not an object or has no member `i`. */
691
+ keyAt(v: JsonValue, i: i32): string {
692
+ const x: i32 = this.index(v)
693
+ if (this.kindAt(x) !== JSON_VALUE_OBJECT) {
694
+ return ""
695
+ }
696
+ const s: i32 = this.slotAt(x, i)
697
+ if (s < 0) {
698
+ return ""
699
+ }
700
+ return this.textOf(jsonValueGet(this.slotKeyAt, s), jsonValueGet(this.slotKeyLength, s))
701
+ }
702
+
703
+ /** The value of the member of object `v` whose key is `key`'s bytes; `-1` when there is none. */
704
+ get(v: JsonValue, key: string): JsonValue {
705
+ const x: i32 = this.index(v)
706
+ if (this.kindAt(x) !== JSON_VALUE_OBJECT) {
707
+ return -1
708
+ }
709
+ const s: i32 = this.findKey(x, key)
710
+ return s < 0 ? -1 : this.handle(jsonValueGet(this.slotValue, s))
711
+ }
712
+
713
+ /** Internal: the slot of the member of the object at index `x` whose key is `key`'s bytes, or `-1`. */
714
+ findKey(x: i32, key: string): i32 {
715
+ const start: i32 = jsonValueGet(this.first, x)
716
+ const n: i32 = jsonValueGet(this.count, x)
717
+ for (let s: i32 = start; s < start + n; s += 1) {
718
+ if (this.bytesEqual(jsonValueGet(this.slotKeyAt, s), jsonValueGet(this.slotKeyLength, s), key)) {
719
+ return s
720
+ }
721
+ }
722
+ return -1
723
+ }
724
+
725
+ /** A string's decoded bytes as a string; `""` for any other value. */
726
+ string(v: JsonValue): string {
727
+ const x: i32 = this.index(v)
728
+ if (this.kindAt(x) !== JSON_VALUE_STRING) {
729
+ return ""
730
+ }
731
+ return this.textOf(jsonValueGet(this.first, x), jsonValueGet(this.count, x))
732
+ }
733
+
734
+ /** Whether `v` is a string whose decoded bytes are `s`'s. Allocates nothing. */
735
+ stringEquals(v: JsonValue, s: string): boolean {
736
+ const x: i32 = this.index(v)
737
+ return (
738
+ this.kindAt(x) === JSON_VALUE_STRING &&
739
+ this.bytesEqual(jsonValueGet(this.first, x), jsonValueGet(this.count, x), s)
740
+ )
741
+ }
742
+
743
+ /** A number's text, exactly as it was written or built; `""` for any other value. */
744
+ numberText(v: JsonValue): string {
745
+ const x: i32 = this.index(v)
746
+ if (this.kindAt(x) !== JSON_VALUE_NUMBER) {
747
+ return ""
748
+ }
749
+ return this.textOf(jsonValueGet(this.first, x), jsonValueGet(this.count, x))
750
+ }
751
+
752
+ /**
753
+ * Whether `v` is a number written without a fraction or an exponent whose
754
+ * value fits an `i64`: the spelling, so `1.0` is not one. `isIntegral(v)`
755
+ * asks whether the value is whole.
756
+ */
757
+ isI64(v: JsonValue): boolean {
758
+ return this.readNumber(this.index(v)) && this.numbers.isInteger()
759
+ }
760
+
761
+ /** A number's value as an `i64` when `isI64(v)` holds, and `0` otherwise. */
762
+ i64(v: JsonValue): i64 {
763
+ // `numberI64` is already `0` for a number that is not an `i64`.
764
+ return this.readNumber(this.index(v)) ? this.numbers.numberI64() : toI64(0)
765
+ }
766
+
767
+ /**
768
+ * Whether `v` is a number written without a sign, a fraction or an exponent
769
+ * whose value fits a `u64`: the spelling, as `isI64(v)` is.
770
+ */
771
+ isU64(v: JsonValue): boolean {
772
+ this.unsigned(this.index(v))
773
+ return this.unsignedFits
774
+ }
775
+
776
+ /** A number's value as a `u64` when `isU64(v)` holds, and `0` otherwise. */
777
+ u64(v: JsonValue): u64 {
778
+ return this.unsigned(this.index(v))
779
+ }
780
+
781
+ /**
782
+ * Internal: the digits of the number at index `x` as a `u64`, setting
783
+ * `unsignedFits` to whether it is a `u64` at all: no sign, no fraction or
784
+ * exponent, and at most 2^64 - 1. Every `u64` comes from `toU64`, which is
785
+ * a BigInt under Node, and nothing here wraps, so it means the same there.
786
+ */
787
+ unsigned(x: i32): u64 {
788
+ this.unsignedFits = false
789
+ if (!this.readNumber(x) || !this.numbers.integral) {
790
+ return toU64(0)
791
+ }
792
+ const bytes: u8[] = this.bytes
793
+ const start: i32 = jsonValueGet(this.first, x)
794
+ const end: i32 = start + jsonValueGet(this.count, x)
795
+ if (start < 0 || start >= toI32(bytes.length) || toI32(bytes[start]) === JSON_VALUE_MINUS) {
796
+ return toU64(0)
797
+ }
798
+ const ten: u64 = toU64(10)
799
+ // 2^64 - 1 has no literal: 2^16 - 1 widened twice.
800
+ const quarter: u64 = toU64(65535)
801
+ const half: u64 = (quarter << toU64(16)) | quarter
802
+ const max: u64 = (half << toU64(32)) | half
803
+ let acc: u64 = toU64(0)
804
+ for (let i: i32 = start; i < end && i < toI32(bytes.length); i += 1) {
805
+ const digit: u64 = toU64(toI32(bytes[i]) - JSON_VALUE_DIGIT_0)
806
+ if (acc > (max - digit) / ten) {
807
+ return toU64(0)
808
+ }
809
+ acc = acc * ten + digit
810
+ }
811
+ this.unsignedFits = true
812
+ return acc
813
+ }
814
+
815
+ /**
816
+ * Whether `v` is a number whose value is whole, however it is written:
817
+ * JSON Schema 2020-12's "integer", the tokenizer's `isIntegral`. `1.0`,
818
+ * `1e2` and `1e400` are, where `isI64(v)` and `isU64(v)` go by spelling and
819
+ * by range and answer `false` for all three. `false` for any other kind and
820
+ * for a handle from an earlier parse.
821
+ */
822
+ isIntegral(v: JsonValue): boolean {
823
+ return this.readNumber(this.index(v)) && this.numbers.isIntegral()
824
+ }
825
+
826
+ /** A number's nearest `f64`, ties to even, as `JSON.parse` reads it; `0` for any other value. */
827
+ f64(v: JsonValue): f64 {
828
+ if (!this.readNumber(this.index(v))) {
829
+ return 0
830
+ }
831
+ return this.numbers.numberF64()
832
+ }
833
+
834
+ /** Internal: points the number tokenizer at index `x`'s text and reads its one token; `false` when it is not a number. */
835
+ readNumber(x: i32): boolean {
836
+ if (this.kindAt(x) !== JSON_VALUE_NUMBER) {
837
+ return false
838
+ }
839
+ const numbers: JsonTokenizer = this.numbers
840
+ numbers.reset(this.bytes, jsonValueGet(this.first, x), jsonValueGet(this.count, x))
841
+ return numbers.next() === JSON_TOK_NUMBER
842
+ }
843
+
844
+ /** Internal: `bytes[at, at + n)` as a string, in one allocation. */
845
+ textOf(at: i32, n: i32): string {
846
+ const bytes: u8[] = this.bytes
847
+ if (at < 0 || n <= 0 || at > toI32(bytes.length) - n) {
848
+ return ""
849
+ }
850
+ return String.fromBytes(bytes, at, at + n)
851
+ }
852
+
853
+ /** Internal: whether `bytes[at, at + n)` are exactly `s`'s bytes. */
854
+ bytesEqual(at: i32, n: i32, s: string): boolean {
855
+ const bytes: u8[] = this.bytes
856
+ if (toI32(s.length) !== n || at < 0 || at > toI32(bytes.length) - n) {
857
+ return false
858
+ }
859
+ for (let i: i32 = 0; i < n && i < toI32(s.length) && at + i < toI32(bytes.length); i += 1) {
860
+ if (toI32(bytes[at + i]) !== toI32(s.charCodeAt(i))) {
861
+ return false
862
+ }
863
+ }
864
+ return true
865
+ }
866
+
867
+ // ---- Building ---------------------------------------------------------------
868
+ // Each `new*` answers a handle, or `JSON_VALUE_ERR_VALUES` when the document
869
+ // already holds `maxValues`.
870
+
871
+ newNull(): JsonValue {
872
+ return this.handle(this.newNode(JSON_VALUE_NULL, JSON_VALUE_NO_WORD, JSON_VALUE_NO_WORD))
873
+ }
874
+
875
+ newBoolean(b: boolean): JsonValue {
876
+ return this.handle(
877
+ this.newNode(JSON_VALUE_BOOLEAN, b ? JSON_VALUE_TRUE_WORD : JSON_VALUE_NO_WORD, JSON_VALUE_NO_WORD)
878
+ )
879
+ }
880
+
881
+ /** A string holding `s`'s bytes. */
882
+ newString(s: string): JsonValue {
883
+ return this.newStored(JSON_VALUE_STRING, s)
884
+ }
885
+
886
+ /** A number holding `x`'s digits. */
887
+ newI64(x: i64): JsonValue {
888
+ return this.newStored(JSON_VALUE_NUMBER, `${x}`)
889
+ }
890
+
891
+ /** A number holding `x`'s digits. */
892
+ newU64(x: u64): JsonValue {
893
+ return this.newStored(JSON_VALUE_NUMBER, `${x}`)
894
+ }
895
+
896
+ /**
897
+ * A number holding `x` as `String(x)` spells it, the shortest digits that
898
+ * read back as `x`, with `-0` as `0`: what `JsonWriter.f64` writes.
899
+ * `JSON_VALUE_ERR_NUMBER` for NaN and both infinities, which JSON cannot
900
+ * spell.
901
+ */
902
+ newF64(x: f64): JsonValue {
903
+ // `x - x` is `0` for every finite `x`, and NaN for NaN and both infinities.
904
+ if (x - x !== toF64(0)) {
905
+ return JSON_VALUE_ERR_NUMBER
906
+ }
907
+ return this.newStored(JSON_VALUE_NUMBER, `${x}`)
908
+ }
909
+
910
+ /**
911
+ * A number holding `text` exactly, which must be one JSON number and
912
+ * nothing else (RFC 8259 §6); `JSON_VALUE_ERR_NUMBER` otherwise. This is how
913
+ * a program writes a number no integer or float type holds.
914
+ */
915
+ newNumber(text: string): JsonValue {
916
+ const at: i32 = this.byteTop
917
+ const n: i32 = this.storeText(text)
918
+ const numbers: JsonTokenizer = this.numbers
919
+ numbers.reset(this.bytes, at, n)
920
+ // The tokenizer allows blanks around a value, and a number here is the text alone.
921
+ const isNumber: boolean =
922
+ numbers.next() === JSON_TOK_NUMBER && numbers.tokStart === at && numbers.tokEnd === at + n
923
+ if (!isNumber || numbers.next() !== JSON_TOK_END) {
924
+ this.byteTop = at
925
+ return JSON_VALUE_ERR_NUMBER
926
+ }
927
+ return this.handle(this.newNode(JSON_VALUE_NUMBER, at, n))
928
+ }
929
+
930
+ newArray(): JsonValue {
931
+ return this.handle(this.newNode(JSON_VALUE_ARRAY, this.slotTop, JSON_VALUE_NO_WORD))
932
+ }
933
+
934
+ newObject(): JsonValue {
935
+ return this.handle(this.newNode(JSON_VALUE_OBJECT, this.slotTop, JSON_VALUE_NO_WORD))
936
+ }
937
+
938
+ /** Appends `v` to array `a`. `JSON_VALUE_OK`, or `JSON_VALUE_ERR_HANDLE` or `JSON_VALUE_ERR_ATTACHED`. */
939
+ push(a: JsonValue, v: JsonValue): i32 {
940
+ const ax: i32 = this.index(a)
941
+ const vx: i32 = this.index(v)
942
+ if (this.kindAt(ax) !== JSON_VALUE_ARRAY) {
943
+ return JSON_VALUE_ERR_HANDLE
944
+ }
945
+ const code: i32 = this.adoptable(ax, vx)
946
+ if (code < 0) {
947
+ return code
948
+ }
949
+ this.append(ax, vx, JSON_VALUE_NO_WORD, JSON_VALUE_NO_WORD)
950
+ return JSON_VALUE_OK
951
+ }
952
+
953
+ /**
954
+ * Sets member `key` of object `o` to `v`: in place, keeping its position,
955
+ * when `o` has the key, and appended last when it does not, as assigning a
956
+ * property of a JavaScript object does. The value it replaces leaves the
957
+ * object and is in no container afterwards. `JSON_VALUE_OK`, or
958
+ * `JSON_VALUE_ERR_HANDLE` or `JSON_VALUE_ERR_ATTACHED`.
959
+ */
960
+ set(o: JsonValue, key: string, v: JsonValue): i32 {
961
+ const ox: i32 = this.index(o)
962
+ const vx: i32 = this.index(v)
963
+ if (this.kindAt(ox) !== JSON_VALUE_OBJECT) {
964
+ return JSON_VALUE_ERR_HANDLE
965
+ }
966
+ const code: i32 = this.adoptable(ox, vx)
967
+ if (code < 0) {
968
+ return code
969
+ }
970
+ const s: i32 = this.findKey(ox, key)
971
+ if (s >= 0) {
972
+ jsonValuePut(this.parent, jsonValueGet(this.slotValue, s), -1)
973
+ jsonValuePut(this.slotValue, s, vx)
974
+ jsonValuePut(this.parent, vx, ox)
975
+ return JSON_VALUE_OK
976
+ }
977
+ this.append(ox, vx, this.byteTop, this.storeText(key))
978
+ return JSON_VALUE_OK
979
+ }
980
+
981
+ /**
982
+ * Internal: whether the value at index `v` may go into the container at
983
+ * index `c`: it is a value, it is in no container, and it is not `c` or a
984
+ * container `c` is inside. Through `push` and `set`, that is what keeps
985
+ * every tree finite.
986
+ */
987
+ adoptable(c: i32, v: i32): i32 {
988
+ if (this.kindAt(v) === JSON_VALUE_NONE) {
989
+ return JSON_VALUE_ERR_HANDLE
990
+ }
991
+ if (jsonValueGet(this.parent, v) >= 0) {
992
+ return JSON_VALUE_ERR_ATTACHED
993
+ }
994
+ let p: i32 = c
995
+ while (p >= 0) {
996
+ if (p === v) {
997
+ return JSON_VALUE_ERR_ATTACHED
998
+ }
999
+ p = jsonValueGet(this.parent, p)
1000
+ }
1001
+ return JSON_VALUE_OK
1002
+ }
1003
+
1004
+ /**
1005
+ * Internal: adds index `v`, with the key `bytes[keyAt, keyAt + keyLength)`,
1006
+ * after the last member of index `c`, unchecked: `push` and `set` check
1007
+ * first. A container whose slots are full moves them to the end of the slot
1008
+ * arrays with twice the room, unless they are at the end already, where they
1009
+ * grow in place; the slots it leaves are not reused until `clear`.
1010
+ */
1011
+ append(c: i32, v: i32, keyAt: i32, keyLength: i32): void {
1012
+ let start: i32 = jsonValueGet(this.first, c)
1013
+ const n: i32 = jsonValueGet(this.count, c)
1014
+ const capacity: i32 = jsonValueGet(this.room, c)
1015
+ if (n === capacity) {
1016
+ const grown: i32 = capacity < JSON_VALUE_FIRST_SLOTS ? JSON_VALUE_FIRST_SLOTS : capacity * 2
1017
+ if (start + capacity !== this.slotTop) {
1018
+ const moved: i32 = this.slotTop
1019
+ for (let i: i32 = 0; i < n; i += 1) {
1020
+ jsonValuePut(this.slotValue, moved + i, jsonValueGet(this.slotValue, start + i))
1021
+ jsonValuePut(this.slotKeyAt, moved + i, jsonValueGet(this.slotKeyAt, start + i))
1022
+ jsonValuePut(this.slotKeyLength, moved + i, jsonValueGet(this.slotKeyLength, start + i))
1023
+ }
1024
+ start = moved
1025
+ jsonValuePut(this.first, c, start)
1026
+ }
1027
+ this.slotTop = start + grown
1028
+ this.slotValue = jsonValueRoomI32(this.slotValue, this.slotTop)
1029
+ this.slotKeyAt = jsonValueRoomI32(this.slotKeyAt, this.slotTop)
1030
+ this.slotKeyLength = jsonValueRoomI32(this.slotKeyLength, this.slotTop)
1031
+ jsonValuePut(this.room, c, grown)
1032
+ }
1033
+ jsonValuePut(this.slotValue, start + n, v)
1034
+ jsonValuePut(this.slotKeyAt, start + n, keyAt)
1035
+ jsonValuePut(this.slotKeyLength, start + n, keyLength)
1036
+ jsonValuePut(this.count, c, n + 1)
1037
+ jsonValuePut(this.parent, v, c)
1038
+ }
1039
+
1040
+ /** Internal: a new value of `kind` holding `s`'s bytes, as a handle. */
1041
+ newStored(kind: i32, s: string): JsonValue {
1042
+ return this.handle(this.newNode(kind, this.byteTop, this.storeText(s)))
1043
+ }
1044
+
1045
+ /** Internal: `s`'s bytes onto the end of `bytes`; answers how many. */
1046
+ storeText(s: string): i32 {
1047
+ const n: i32 = toI32(s.length)
1048
+ const at: i32 = this.byteTop
1049
+ const buf: u8[] = jsonValueRoom(this.bytes, at + n)
1050
+ this.bytes = buf
1051
+ for (let i: i32 = 0; i < n && at + i < toI32(buf.length); i += 1) {
1052
+ if (at + i >= 0) {
1053
+ buf[at + i] = toU8(s.charCodeAt(i))
1054
+ }
1055
+ }
1056
+ this.byteTop = at + n
1057
+ return n
1058
+ }
1059
+
1060
+ // ---- Writing ----------------------------------------------------------------
1061
+
1062
+ /**
1063
+ * Writes `v` into `w` as one value, members in order and numbers as their
1064
+ * text; the outcome is the writer's, in `w.failed`. A value that names
1065
+ * nothing writes nothing and fails nothing. A parsed tree is never deeper
1066
+ * than the writer nests; a built one deeper than `JSON_WRITER_MAX_DEPTH`
1067
+ * ends at `JSON_WRITE_TOO_DEEP`, where the recursion stops.
1068
+ */
1069
+ write(v: JsonValue, w: JsonWriter): void {
1070
+ this.writeAt(this.index(v), w)
1071
+ }
1072
+
1073
+ /** Internal: `write` of index `x`. */
1074
+ writeAt(x: i32, w: JsonWriter): void {
1075
+ const k: i32 = this.kindAt(x)
1076
+ if (k === JSON_VALUE_NONE || w.failed !== JSON_WRITE_OK) {
1077
+ return
1078
+ }
1079
+ if (k === JSON_VALUE_NULL) {
1080
+ w.nullValue()
1081
+ } else if (k === JSON_VALUE_BOOLEAN) {
1082
+ w.boolean(jsonValueGet(this.first, x) === JSON_VALUE_TRUE_WORD)
1083
+ } else if (k === JSON_VALUE_NUMBER) {
1084
+ w.raw(this.bytes, jsonValueGet(this.first, x), jsonValueGet(this.count, x))
1085
+ } else if (k === JSON_VALUE_STRING) {
1086
+ w.stringBytes(this.bytes, jsonValueGet(this.first, x), jsonValueGet(this.count, x))
1087
+ } else {
1088
+ // A container: its members are the slots from `first`, read directly.
1089
+ const object: boolean = k === JSON_VALUE_OBJECT
1090
+ const start: i32 = jsonValueGet(this.first, x)
1091
+ const end: i32 = start + jsonValueGet(this.count, x)
1092
+ if (object) {
1093
+ w.beginObject()
1094
+ } else {
1095
+ w.beginArray()
1096
+ }
1097
+ for (let s: i32 = start; s < end && w.failed === JSON_WRITE_OK; s += 1) {
1098
+ if (object) {
1099
+ w.keyBytes(this.bytes, jsonValueGet(this.slotKeyAt, s), jsonValueGet(this.slotKeyLength, s))
1100
+ }
1101
+ this.writeAt(jsonValueGet(this.slotValue, s), w)
1102
+ }
1103
+ if (object) {
1104
+ w.endObject()
1105
+ } else {
1106
+ w.endArray()
1107
+ }
1108
+ }
1109
+ }
1110
+
1111
+ /**
1112
+ * `v` as minified JSON text: written into a buffer that doubles until it
1113
+ * fits, then made into one string. `""` when `v` names nothing or the
1114
+ * writer refuses it, which only a built tree deeper than
1115
+ * `JSON_WRITER_MAX_DEPTH` makes it do; `write` gives the code.
1116
+ */
1117
+ stringify(v: JsonValue): string {
1118
+ // Every byte stored and a few of punctuation per value: one pass fits most
1119
+ // documents, and a text with many escapes doubles from there.
1120
+ let size: i32 = this.byteTop + 8 * this.top + 64
1121
+ while (true) {
1122
+ const buf: u8[] = new Array<u8>(size)
1123
+ const w: JsonWriter = new JsonWriter(buf, 0)
1124
+ this.write(v, w)
1125
+ if (w.failed !== JSON_WRITE_FULL || size > JSON_VALUE_I32_MAX / 2) {
1126
+ return w.complete() && w.end <= toI32(buf.length) ? String.fromBytes(buf, 0, w.end) : ""
1127
+ }
1128
+ size = size * 2
1129
+ }
1130
+ }
1131
+ }
1132
+
1133
+ /** `a[i]`, or `-1` when `i` is outside `a`. */
1134
+ const jsonValueGet = (a: i32[], i: i32): i32 => (i >= 0 && i < toI32(a.length) ? a[i] : -1)
1135
+
1136
+ /** `a[i] = x`, growing `a` by one when `i` is its length; an `i` further out writes nothing. */
1137
+ const jsonValuePut = (a: i32[], i: i32, x: i32): void => {
1138
+ if (i >= 0 && i < toI32(a.length)) {
1139
+ a[i] = x
1140
+ } else if (i === toI32(a.length)) {
1141
+ a.push(x)
1142
+ }
1143
+ }
1144
+
1145
+ /**
1146
+ * `a` when it holds at least `n` elements, and otherwise a copy of it at
1147
+ * least twice as long, for the caller to keep in `a`'s place. Doubling is
1148
+ * what keeps a run of appends linear, and the old array is left in the arena.
1149
+ */
1150
+ const jsonValueRoom = (a: u8[], n: i32): u8[] => {
1151
+ const have: i32 = toI32(a.length)
1152
+ if (n <= have) {
1153
+ return a
1154
+ }
1155
+ const grown: u8[] = new Array<u8>(n > have * 2 ? n : have * 2)
1156
+ grown.set(a, 0)
1157
+ return grown
1158
+ }
1159
+
1160
+ /** `jsonValueRoom` for an `i32[]`. */
1161
+ const jsonValueRoomI32 = (a: i32[], n: i32): i32[] => {
1162
+ const have: i32 = toI32(a.length)
1163
+ if (n <= have) {
1164
+ return a
1165
+ }
1166
+ const grown: i32[] = new Array<i32>(n > have * 2 ? n : have * 2)
1167
+ grown.set(a, 0)
1168
+ return grown
1169
+ }
1170
+
1171
+ /** `bytes[a, a + an)` and `bytes[b, b + bn)` compared byte by byte, a shorter prefix first: negative, `0` or positive. */
1172
+ const jsonValueCompareBytes = (bytes: u8[], a: i32, an: i32, b: i32, bn: i32): i32 => {
1173
+ const n: i32 = an < bn ? an : bn
1174
+ for (let i: i32 = 0; i < n; i += 1) {
1175
+ const x: i32 = a + i >= 0 && a + i < toI32(bytes.length) ? toI32(bytes[a + i]) : 0
1176
+ const y: i32 = b + i >= 0 && b + i < toI32(bytes.length) ? toI32(bytes[b + i]) : 0
1177
+ if (x !== y) {
1178
+ return x - y
1179
+ }
1180
+ }
1181
+ return an - bn
1182
+ }