@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,1014 @@
1
+ /**
2
+ * `nish/json-typed` — decode a JSON object into a class, and encode a class
3
+ * back, with code the compiler writes from the class's fields.
4
+ *
5
+ * import { JsonLimits } from "nish/json-tokenizer";
6
+ * import { JsonWriter } from "nish/json";
7
+ * import { JsonDecoder, jsonDecode, jsonEncode } from "nish/json-typed";
8
+ *
9
+ * class Point { x: i32 = 0; y: i32 = 0 }
10
+ *
11
+ * const d = new JsonDecoder(body, 0, toI32(body.length), new JsonLimits());
12
+ * const p = new Point();
13
+ * if (jsonDecode(d, p) === 0) {
14
+ * const w = new JsonWriter(out, 0);
15
+ * jsonEncode(w, p); // out[0 .. w.end) is {"x":..,"y":..}
16
+ * }
17
+ *
18
+ * **What is generated, and from what.** `jsonDecode(d, out)` and
19
+ * `jsonEncode(w, value)` are generic, and the bodies written below are not
20
+ * what runs natively: the compiler lowers every call in place, in the module
21
+ * that makes it, to code it writes from the layout of the class the call
22
+ * binds `T` to (`src/json-typed.ts`, `src/emit-json.ts`). That code is
23
+ * straight-line calls into the methods of `JsonDecoder` and the functions
24
+ * here for each field, and into `JsonWriter`'s, so all of the parsing is the
25
+ * tokenizer's and all of the writing is the writer's. A field may be an
26
+ * `i32`, `u32`, `i64`, `u64`, `f64` (or `number`), `boolean` or `string`, a
27
+ * numeric enum (its number), a class decoded the same way, a `JsonNumber`, an
28
+ * array of any of those, a `Map<string, V>` (a JSON object) whose `V` is any
29
+ * of these, or a string, class, array or map `| null`; anything else is
30
+ * refused at the call, naming the field (docs/LANGUAGE.md, "Typed JSON").
31
+ *
32
+ * **The decoding rules.** A JSON object's keys are the class's field names,
33
+ * byte for byte, or the keys its options give them, found by the key's length
34
+ * and then, among three or more names of that length, by one of its bytes:
35
+ *
36
+ * class Account {
37
+ * static readonly json = { rename: { userId: "user_id" }, optional: ["tags"] };
38
+ * ...
39
+ * }
40
+ *
41
+ * The compiler reads that literal; it is not a field. Every field is required
42
+ * but an optional one, whose missing key sets it to its initializer, a key
43
+ * may appear once, and a key that names no field is an error unless
44
+ * `ignoreUnknown` is set, when its value is stepped over. A number must fit its field: an integer field takes
45
+ * an integer written without a fraction or an exponent and in the field's
46
+ * range, and `f64` takes any number. `null` is accepted only by a field whose
47
+ * type is `| null`. Fields are written to `out` as they are read, in the
48
+ * input's order: a nested object is decoded into the object the field already
49
+ * holds, an array's elements into the elements it already has (so a reused
50
+ * object reuses its arrays and objects, and `Arena.used()` stays flat), and a
51
+ * string field keeps the string it holds when the input's is equal.
52
+ * A class the decoder has to make — an array element past the array's end, a
53
+ * `| null` field that holds `null`, or a map's value — is made with `new C()`.
54
+ * A map is emptied and filled in the input's order, and every map of one
55
+ * decoding takes at most `maxMapKeys` keys between them.
56
+ *
57
+ * **Errors are sticky codes**, as the tokenizer's and the writer's are. The
58
+ * first error sets `failed` to a negative code — a `JSON_DECODE_*` code here,
59
+ * or the tokenizer's own `JSON_TOK_ERR_*` code when the text is not JSON or
60
+ * crosses one of its `JsonLimits` — and `errorAt` to the byte offset of the
61
+ * token it was found at. Every later call does nothing, and `jsonDecode`
62
+ * answers `failed`. Nothing an input holds panics. After an error, `out` holds
63
+ * a value of its type in every field, some of them decoded and some as they
64
+ * were.
65
+ *
66
+ * **Encoding** writes the fields in declaration order, each through the
67
+ * writer method of its type, so the text is what `JSON.stringify` writes for
68
+ * the same object; the writer's own sticky code reports a full buffer.
69
+ *
70
+ * **Under Node** the types are erased, so there is no layout to generate the
71
+ * code from: `jsonDecode` and `jsonEncode` end the program with a panic
72
+ * naming this, rather than guessing a type from whatever value a field holds
73
+ * (docs/LANGUAGE.md, "Typed JSON", class C). Everything else here runs there.
74
+ *
75
+ * Every name here is `json`-prefixed, as `std/json.ts` explains, and every
76
+ * code is an `i32`, so the module is the same under `--number-mode f64`.
77
+ */
78
+ import { JsonWriter } from "nish/json"
79
+ import {
80
+ JSON_TOK_ARRAY_BEGIN,
81
+ JSON_TOK_ARRAY_END,
82
+ JSON_TOK_END,
83
+ JSON_TOK_FALSE,
84
+ JSON_TOK_KEY,
85
+ JSON_TOK_NULL,
86
+ JSON_TOK_NUMBER,
87
+ JSON_TOK_OBJECT_BEGIN,
88
+ JSON_TOK_STRING,
89
+ JSON_TOK_TRUE,
90
+ JsonLimits,
91
+ JsonTokenizer,
92
+ } from "nish/json-tokenizer"
93
+
94
+ /** Nothing has failed. */
95
+ export const JSON_DECODE_OK: i32 = 0
96
+ /** A value of the wrong JSON type for its field: a string for an `i32`, an array for a class, `null` for a field that is not `| null`. */
97
+ export const JSON_DECODE_TYPE: i32 = -20
98
+ /** A number its field cannot hold: a fraction or an exponent for an integer field, or a value outside its range. */
99
+ export const JSON_DECODE_RANGE: i32 = -21
100
+ /** A key that names no field of the class, while `ignoreUnknown` is off. */
101
+ export const JSON_DECODE_UNKNOWN: i32 = -22
102
+ /** A key that names a field the object already gave. */
103
+ export const JSON_DECODE_DUPLICATE: i32 = -23
104
+ /** An object that ended without one of the class's fields; `errorAt` is its closing brace. */
105
+ export const JSON_DECODE_MISSING: i32 = -24
106
+ /**
107
+ * More keys, over every `Map` field one decoding fills, than `maxMapKeys`;
108
+ * `errorAt` is the first key past the limit. The global `Map` hashes a
109
+ * string with no seed, so a body can choose keys that all collide, and the
110
+ * limit bounds what the maps' probes cost over the whole decoding
111
+ * (docs/security/json.md, JSON-13).
112
+ */
113
+ export const JSON_DECODE_MAP_LIMIT: i32 = -25
114
+
115
+ /** What a program running under Node is told, where the compiler would have written the code. */
116
+ const JSON_TYPED_ERASED: string =
117
+ "nish/json-typed: jsonDecode and jsonEncode are written by the compiler from the class's fields, and under Node the types are erased"
118
+
119
+ /**
120
+ * A JSON number kept as the text it was written in, so that no digit is lost:
121
+ * an integer wider than a `u64` and a fraction with more digits than an `f64`
122
+ * holds are decoded and encoded again byte for byte. A field of this class is
123
+ * read and written as one number, not as an object: `jsonDecode` copies the
124
+ * number's text into it, and `jsonEncode` writes that text back unchanged.
125
+ *
126
+ * It reads its text as `nish/json-value` reads a number (`numberText`,
127
+ * `isI64`, `i64`, `isU64`, `u64`, `f64`), through a tokenizer of its own, so
128
+ * the two answer alike; the two are separate types until the typed layer
129
+ * can name a `JsonValue`'s number directly.
130
+ *
131
+ * A new one holds `0`. Decoding into one reuses its bytes, so an object
132
+ * decoded again with numbers no longer than before allocates nothing for
133
+ * them.
134
+ */
135
+ export class JsonNumber {
136
+ /** The text is `bytes[0, count)`, one JSON number; the bytes past it are room. */
137
+ bytes: u8[]
138
+ count: i32 = 1
139
+
140
+ constructor() {
141
+ this.bytes = [48]
142
+ }
143
+
144
+ /** The number's text, exactly as it was written or set. */
145
+ text(): string {
146
+ return String.fromBytes(this.bytes, 0, this.count)
147
+ }
148
+
149
+ /**
150
+ * A tokenizer over the text, read to its one token. It may open no
151
+ * container and take a number of any length, so it allocates no stack.
152
+ */
153
+ reader(): JsonTokenizer {
154
+ const limits: JsonLimits = new JsonLimits()
155
+ limits.maxDepth = 0
156
+ limits.maxNumberBytes = this.count
157
+ const tok: JsonTokenizer = new JsonTokenizer(this.bytes, 0, this.count, limits)
158
+ tok.next()
159
+ return tok
160
+ }
161
+
162
+ /** Whether the number is written without a fraction or an exponent and its value fits an `i64`. */
163
+ isI64(): boolean {
164
+ return this.reader().isInteger()
165
+ }
166
+
167
+ /** The value as an `i64` when `isI64()` holds, and `0` otherwise. */
168
+ i64(): i64 {
169
+ return this.reader().numberI64()
170
+ }
171
+
172
+ /** Whether the number is written in digits alone, with no sign, fraction or exponent, and fits a `u64`. */
173
+ isU64(): boolean {
174
+ return this.reader().isU64()
175
+ }
176
+
177
+ /** The value as a `u64` when `isU64()` holds, and `0` otherwise. */
178
+ u64(): u64 {
179
+ return this.reader().numberU64()
180
+ }
181
+
182
+ /** The nearest `f64`, ties to even, as `JSON.parse` reads it. */
183
+ f64(): f64 {
184
+ return this.reader().numberF64()
185
+ }
186
+
187
+ /**
188
+ * Sets the text to `text` when it is one JSON number and nothing else, and
189
+ * answers whether it was; any other text leaves the number as it was.
190
+ */
191
+ setText(text: string): boolean {
192
+ const n: i32 = toI32(text.length)
193
+ const bytes: u8[] = new Array<u8>(n)
194
+ for (let k: i32 = 0; k < n && k < toI32(bytes.length); k += 1) {
195
+ let c: i32 = toI32(text.charCodeAt(k))
196
+ // A number is ASCII; anything wider fails the check below as `~` does.
197
+ if (c > 127) {
198
+ c = 126
199
+ }
200
+ bytes[k] = toU8(c)
201
+ }
202
+ const limits: JsonLimits = new JsonLimits()
203
+ limits.maxDepth = 0
204
+ limits.maxNumberBytes = n
205
+ const tok: JsonTokenizer = new JsonTokenizer(bytes, 0, n, limits)
206
+ const isNumber: boolean = tok.next() === JSON_TOK_NUMBER && tok.tokStart === 0 && tok.tokEnd === n
207
+ if (!isNumber || tok.next() !== JSON_TOK_END) {
208
+ return false
209
+ }
210
+ this.bytes = bytes
211
+ this.count = n
212
+ return true
213
+ }
214
+ }
215
+
216
+ /**
217
+ * One decoding: a tokenizer over the input and the sticky error. Make one per
218
+ * connection and `reset` it per request; nothing it does allocates but the
219
+ * strings it decodes, the arrays it grows and the objects it makes.
220
+ */
221
+ export class JsonDecoder {
222
+ tok: JsonTokenizer
223
+ /** `JSON_DECODE_OK`, or the first `JSON_DECODE_*` or `JSON_TOK_ERR_*` code. */
224
+ failed: i32 = 0
225
+ /** The byte offset in the input of the token the error was found at; `-1` until one. */
226
+ errorAt: i32 = -1
227
+ /**
228
+ * The most keys every `Map` field of one decoding may take together, 4,096
229
+ * unless set; past it, `JSON_DECODE_MAP_LIMIT`. At `0` or below, no map may
230
+ * take a key, so a map's only accepted value is `{}`.
231
+ */
232
+ maxMapKeys: i32 = 4096
233
+ /** The keys the maps of this decoding have taken so far; `reset` clears it. */
234
+ mapKeys: i32 = 0
235
+ /** Step over a key that names no field instead of failing with `JSON_DECODE_UNKNOWN`. */
236
+ ignoreUnknown: boolean = false
237
+ /**
238
+ * Whether the tokenizer's current token is a value nothing has read yet:
239
+ * the first token of an array element, read to see whether the array had
240
+ * ended, or a value `takeNull` found was not `null`.
241
+ */
242
+ held: boolean = false
243
+
244
+ constructor(src: u8[], off: i32, len: i32, limits: JsonLimits) {
245
+ this.tok = new JsonTokenizer(src, off, len, limits)
246
+ }
247
+
248
+ /**
249
+ * Starts over on `src[off, off + len)`, keeping the limits, `ignoreUnknown`
250
+ * and `maxMapKeys`, and clearing any error and the count of map keys taken.
251
+ */
252
+ reset(src: u8[], off: i32, len: i32): void {
253
+ this.tok.reset(src, off, len)
254
+ this.failed = JSON_DECODE_OK
255
+ this.errorAt = -1
256
+ this.held = false
257
+ this.mapKeys = 0
258
+ }
259
+
260
+ /** Records the first error. */
261
+ fail(code: i32, at: i32): void {
262
+ if (this.failed === JSON_DECODE_OK) {
263
+ this.failed = code
264
+ this.errorAt = at
265
+ }
266
+ }
267
+
268
+ /** `JSON_DECODE_TYPE` at the current token, unless the read that found it failed already. */
269
+ wrongType(): void {
270
+ this.fail(JSON_DECODE_TYPE, this.tok.tokStart)
271
+ }
272
+
273
+ /** The kind of the next value's first token, or a negative code; the held token first, when there is one. */
274
+ take(): i32 {
275
+ if (this.failed !== JSON_DECODE_OK) {
276
+ return this.failed
277
+ }
278
+ if (this.held) {
279
+ this.held = false
280
+ return this.tok.kind
281
+ }
282
+ const k: i32 = this.tok.next()
283
+ if (k < 0) {
284
+ this.fail(k, this.tok.errorAt)
285
+ }
286
+ return k
287
+ }
288
+
289
+ /** The next value opens an object; anything else is `JSON_DECODE_TYPE`. */
290
+ beginObject(): boolean {
291
+ const k: i32 = this.take()
292
+ if (k === JSON_TOK_OBJECT_BEGIN) {
293
+ return true
294
+ }
295
+ if (k >= 0) {
296
+ this.wrongType()
297
+ }
298
+ return false
299
+ }
300
+
301
+ /** Reads the next key of the open object, or its end; `false` at the end and after any error. */
302
+ nextField(): boolean {
303
+ if (this.failed !== JSON_DECODE_OK) {
304
+ return false
305
+ }
306
+ const k: i32 = this.tok.next()
307
+ if (k === JSON_TOK_KEY) {
308
+ return true
309
+ }
310
+ if (k < 0) {
311
+ this.fail(k, this.tok.errorAt)
312
+ }
313
+ return false
314
+ }
315
+
316
+ /** Whether the current key is `name`. */
317
+ keyIs(name: string): boolean {
318
+ return this.tok.keyEquals(name)
319
+ }
320
+
321
+ /**
322
+ * The current key's length in bytes once decoded, or `-1` when the current
323
+ * token is not a key: what the code written for a class switches on before
324
+ * it compares a key's bytes with a field's name.
325
+ */
326
+ keyLength(): i32 {
327
+ return this.tok.stringLength()
328
+ }
329
+
330
+ /**
331
+ * Byte `at` of the current key when the key has no escape, so that its
332
+ * bytes are the input's, and `-1` otherwise: for a key with an escape, for
333
+ * an `at` outside it, and when the current token is not a key. A `-1`
334
+ * matches no byte of a field's name, and the code written for a class then
335
+ * compares the key with each name of its length through `keyIs`, which
336
+ * decodes the escapes.
337
+ */
338
+ keyByte(at: i32): i32 {
339
+ const tok: JsonTokenizer = this.tok
340
+ const n: i32 = tok.stringLength()
341
+ if (n !== tok.tokEnd - tok.tokStart - 2 || at < 0 || at >= n) {
342
+ return -1
343
+ }
344
+ const src: u8[] = tok.src
345
+ const i: i32 = tok.tokStart + 1 + at
346
+ if (i < 0 || i >= toI32(src.length)) {
347
+ return -1
348
+ }
349
+ return toI32(src[i])
350
+ }
351
+
352
+ /**
353
+ * Whether the maps of this decoding may take another key, the current one:
354
+ * whether they have taken fewer than `maxMapKeys` between them, counting
355
+ * it as taken when they may. A key is counted here, before its value is
356
+ * read, so the keys of a map inside another map count before the outer
357
+ * key's value is whole, and the total never passes the limit.
358
+ * `JSON_DECODE_MAP_LIMIT` at the key when they may not.
359
+ */
360
+ mapRoom(): boolean {
361
+ if (this.mapKeys < this.maxMapKeys) {
362
+ this.mapKeys += 1
363
+ return true
364
+ }
365
+ this.fail(JSON_DECODE_MAP_LIMIT, this.tok.tokStart)
366
+ return false
367
+ }
368
+
369
+ /** The current key, decoded, as a new string: a `Map` field's key. `""` when the current token is not a key. */
370
+ key(): string {
371
+ return this.text()
372
+ }
373
+
374
+ /**
375
+ * The current key or string as a new string, made by one
376
+ * `String.fromBytes`: straight from the input when it has no escape, and
377
+ * from its unescaped bytes when it has one. `""` when the current token is
378
+ * neither.
379
+ */
380
+ text(): string {
381
+ const tok: JsonTokenizer = this.tok
382
+ const n: i32 = tok.stringLength()
383
+ if (n < 0) {
384
+ return ""
385
+ }
386
+ if (n === tok.tokEnd - tok.tokStart - 2) {
387
+ // No escape, so the bytes between the quotes are the string's, copied
388
+ // once by `String.fromBytes`.
389
+ return String.fromBytes(tok.src, tok.tokStart + 1, tok.tokEnd - 1)
390
+ }
391
+ // The unescaped bytes are a temporary: a caller that keeps only the string
392
+ // it answers gives them back (the call-site reclaim, docs/LANGUAGE.md).
393
+ const bytes: u8[] = new Array<u8>(n)
394
+ const at: i32 = 0
395
+ tok.stringInto(bytes, at)
396
+ return String.fromBytes(bytes, 0, n)
397
+ }
398
+
399
+ /** The current key names no field: stepped over with its value, or `JSON_DECODE_UNKNOWN`. */
400
+ unknownField(): void {
401
+ if (this.failed !== JSON_DECODE_OK) {
402
+ return
403
+ }
404
+ if (!this.ignoreUnknown) {
405
+ this.fail(JSON_DECODE_UNKNOWN, this.tok.tokStart)
406
+ return
407
+ }
408
+ const k: i32 = this.tok.skipValue()
409
+ if (k < 0) {
410
+ this.fail(k, this.tok.errorAt)
411
+ }
412
+ }
413
+
414
+ /** The current key names a field the object already gave. */
415
+ duplicateField(): void {
416
+ this.fail(JSON_DECODE_DUPLICATE, this.tok.tokStart)
417
+ }
418
+
419
+ /** The object just closed without one of the fields. */
420
+ missingField(): void {
421
+ this.fail(JSON_DECODE_MISSING, this.tok.tokStart)
422
+ }
423
+
424
+ /** After the top-level value: nothing but blanks may follow. Answers `failed`. */
425
+ finish(): i32 {
426
+ if (this.failed === JSON_DECODE_OK) {
427
+ const k: i32 = this.tok.next()
428
+ if (k < 0) {
429
+ this.fail(k, this.tok.errorAt)
430
+ } else if (k !== JSON_TOK_END) {
431
+ this.wrongType()
432
+ }
433
+ }
434
+ return this.failed
435
+ }
436
+
437
+ /** Whether the next value is `null`, read if so; otherwise it is held for the read that follows. */
438
+ takeNull(): boolean {
439
+ const k: i32 = this.take()
440
+ if (k === JSON_TOK_NULL) {
441
+ return true
442
+ }
443
+ if (k >= 0) {
444
+ this.held = true
445
+ }
446
+ return false
447
+ }
448
+
449
+ /** The next value opens an array; anything else is `JSON_DECODE_TYPE`. */
450
+ beginArray(): boolean {
451
+ const k: i32 = this.take()
452
+ if (k === JSON_TOK_ARRAY_BEGIN) {
453
+ return true
454
+ }
455
+ if (k >= 0) {
456
+ this.wrongType()
457
+ }
458
+ return false
459
+ }
460
+
461
+ /** Whether the open array has another element, whose first token is then held; `false` at its end and after any error. */
462
+ nextElement(): boolean {
463
+ if (this.failed !== JSON_DECODE_OK) {
464
+ return false
465
+ }
466
+ const k: i32 = this.tok.next()
467
+ if (k === JSON_TOK_ARRAY_END) {
468
+ return false
469
+ }
470
+ if (k < 0) {
471
+ this.fail(k, this.tok.errorAt)
472
+ return false
473
+ }
474
+ this.held = true
475
+ return true
476
+ }
477
+
478
+ /**
479
+ * The next value as an integer, from `lo` to `hi` when `bounded`, or `0`
480
+ * with an error. Every `i64` it answers is the tokenizer's or made with
481
+ * `toI64`, so that under Node, where an `i64` is a BigInt, what a caller
482
+ * computes with it never mixes a BigInt with a number.
483
+ */
484
+ integer(lo: i64, hi: i64, bounded: boolean): i64 {
485
+ const k: i32 = this.take()
486
+ if (k !== JSON_TOK_NUMBER) {
487
+ if (k >= 0) {
488
+ this.wrongType()
489
+ }
490
+ return toI64(0)
491
+ }
492
+ if (!this.tok.isInteger()) {
493
+ this.fail(JSON_DECODE_RANGE, this.tok.tokStart)
494
+ return toI64(0)
495
+ }
496
+ const v: i64 = this.tok.numberI64()
497
+ if (bounded && (v < lo || v > hi)) {
498
+ this.fail(JSON_DECODE_RANGE, this.tok.tokStart)
499
+ return toI64(0)
500
+ }
501
+ return v
502
+ }
503
+
504
+ i32(): i32 {
505
+ const lo: i64 = -2147483648
506
+ const hi: i64 = 2147483647
507
+ return toI32(this.integer(lo, hi, true))
508
+ }
509
+
510
+ /** The bounds are compared and never computed with, so under Node a number beside a BigInt is fine. */
511
+ u32(): u32 {
512
+ const lo: i64 = 0
513
+ const hi: i64 = 4294967295
514
+ // Through `f64`, which holds every `u32` exactly: under Node `toU32` takes
515
+ // no BigInt, and the `i64` the tokenizer answers is one there.
516
+ return toU32(toF64(this.integer(lo, hi, true)))
517
+ }
518
+
519
+ /** Any integer `isInteger` accepts fits an `i64`, so there is no range to check. */
520
+ i64(): i64 {
521
+ return this.integer(toI64(0), toI64(0), false)
522
+ }
523
+
524
+ /**
525
+ * The next value as a `u64`: an integer written in digits alone, with no
526
+ * sign, fraction or exponent, up to 2^64 - 1, read through the tokenizer's
527
+ * `numberU64`. A negative number, `-0` included, and one past 2^64 - 1 are
528
+ * `JSON_DECODE_RANGE`, as a fraction is; `0` with an error.
529
+ */
530
+ u64(): u64 {
531
+ const k: i32 = this.take()
532
+ if (k !== JSON_TOK_NUMBER) {
533
+ if (k >= 0) {
534
+ this.wrongType()
535
+ }
536
+ return toU64(0)
537
+ }
538
+ if (!this.tok.isU64()) {
539
+ this.fail(JSON_DECODE_RANGE, this.tok.tokStart)
540
+ return toU64(0)
541
+ }
542
+ return this.tok.numberU64()
543
+ }
544
+
545
+ /**
546
+ * The next value as a `JsonNumber`: its text, copied into `n`'s bytes
547
+ * exactly as the input writes it. Anything but a number is
548
+ * `JSON_DECODE_TYPE`, and `n` keeps the number it held.
549
+ */
550
+ number(n: JsonNumber): void {
551
+ const k: i32 = this.take()
552
+ if (k !== JSON_TOK_NUMBER) {
553
+ if (k >= 0) {
554
+ this.wrongType()
555
+ }
556
+ return
557
+ }
558
+ const tok: JsonTokenizer = this.tok
559
+ const src: u8[] = tok.src
560
+ const bytes: u8[] = n.bytes
561
+ const start: i32 = tok.tokStart
562
+ const end: i32 = tok.tokEnd
563
+ let copied: i32 = 0
564
+ for (let i: i32 = start; i >= 0 && i < end && i < toI32(src.length); i += 1) {
565
+ // Read into a local first: a push ends what the guard proved about `i`.
566
+ const b: u8 = src[i]
567
+ if (copied < toI32(bytes.length)) {
568
+ bytes[copied] = b
569
+ } else {
570
+ bytes.push(b)
571
+ }
572
+ copied += 1
573
+ }
574
+ n.count = copied
575
+ }
576
+
577
+ f64(): f64 {
578
+ const k: i32 = this.take()
579
+ if (k === JSON_TOK_NUMBER) {
580
+ return this.tok.numberF64()
581
+ }
582
+ if (k >= 0) {
583
+ this.wrongType()
584
+ }
585
+ return 0
586
+ }
587
+
588
+ boolean(): boolean {
589
+ const k: i32 = this.take()
590
+ if (k === JSON_TOK_TRUE) {
591
+ return true
592
+ }
593
+ if (k !== JSON_TOK_FALSE && k >= 0) {
594
+ this.wrongType()
595
+ }
596
+ return false
597
+ }
598
+
599
+ /**
600
+ * The next value as a string: `cur` itself when the input's string is equal
601
+ * to it, which allocates nothing, and a new string otherwise; `cur` with an
602
+ * error.
603
+ */
604
+ string(cur: string): string {
605
+ const k: i32 = this.take()
606
+ if (k !== JSON_TOK_STRING) {
607
+ if (k >= 0) {
608
+ this.wrongType()
609
+ }
610
+ return cur
611
+ }
612
+ if (this.tok.keyEquals(cur)) {
613
+ return cur
614
+ }
615
+ return this.text()
616
+ }
617
+
618
+ // Arrays of scalars and strings: each element is read into the slot the
619
+ // array already has, or pushed past its end, and what is left over is
620
+ // popped, so an array of the same length grows nothing.
621
+
622
+ i32Array(xs: i32[]): i32[] {
623
+ if (!this.beginArray()) {
624
+ return xs
625
+ }
626
+ let n: i32 = 0
627
+ while (this.nextElement()) {
628
+ const v: i32 = this.i32()
629
+ if (n < toI32(xs.length)) {
630
+ xs[n] = v
631
+ } else {
632
+ xs.push(v)
633
+ }
634
+ n += 1
635
+ }
636
+ while (toI32(xs.length) > n && xs.length > 0) {
637
+ xs.pop()
638
+ }
639
+ return xs
640
+ }
641
+
642
+ u32Array(xs: u32[]): u32[] {
643
+ if (!this.beginArray()) {
644
+ return xs
645
+ }
646
+ let n: i32 = 0
647
+ while (this.nextElement()) {
648
+ const v: u32 = this.u32()
649
+ if (n < toI32(xs.length)) {
650
+ xs[n] = v
651
+ } else {
652
+ xs.push(v)
653
+ }
654
+ n += 1
655
+ }
656
+ while (toI32(xs.length) > n && xs.length > 0) {
657
+ xs.pop()
658
+ }
659
+ return xs
660
+ }
661
+
662
+ i64Array(xs: i64[]): i64[] {
663
+ if (!this.beginArray()) {
664
+ return xs
665
+ }
666
+ let n: i32 = 0
667
+ while (this.nextElement()) {
668
+ const v: i64 = this.i64()
669
+ if (n < toI32(xs.length)) {
670
+ xs[n] = v
671
+ } else {
672
+ xs.push(v)
673
+ }
674
+ n += 1
675
+ }
676
+ while (toI32(xs.length) > n && xs.length > 0) {
677
+ xs.pop()
678
+ }
679
+ return xs
680
+ }
681
+
682
+ u64Array(xs: u64[]): u64[] {
683
+ if (!this.beginArray()) {
684
+ return xs
685
+ }
686
+ let n: i32 = 0
687
+ while (this.nextElement()) {
688
+ const v: u64 = this.u64()
689
+ if (n < toI32(xs.length)) {
690
+ xs[n] = v
691
+ } else {
692
+ xs.push(v)
693
+ }
694
+ n += 1
695
+ }
696
+ while (toI32(xs.length) > n && xs.length > 0) {
697
+ xs.pop()
698
+ }
699
+ return xs
700
+ }
701
+
702
+ f64Array(xs: f64[]): f64[] {
703
+ if (!this.beginArray()) {
704
+ return xs
705
+ }
706
+ let n: i32 = 0
707
+ while (this.nextElement()) {
708
+ const v: f64 = this.f64()
709
+ if (n < toI32(xs.length)) {
710
+ xs[n] = v
711
+ } else {
712
+ xs.push(v)
713
+ }
714
+ n += 1
715
+ }
716
+ while (toI32(xs.length) > n && xs.length > 0) {
717
+ xs.pop()
718
+ }
719
+ return xs
720
+ }
721
+
722
+ booleanArray(xs: boolean[]): boolean[] {
723
+ if (!this.beginArray()) {
724
+ return xs
725
+ }
726
+ let n: i32 = 0
727
+ while (this.nextElement()) {
728
+ const v: boolean = this.boolean()
729
+ if (n < toI32(xs.length)) {
730
+ xs[n] = v
731
+ } else {
732
+ xs.push(v)
733
+ }
734
+ n += 1
735
+ }
736
+ while (toI32(xs.length) > n && xs.length > 0) {
737
+ xs.pop()
738
+ }
739
+ return xs
740
+ }
741
+
742
+ stringArray(xs: string[]): string[] {
743
+ if (!this.beginArray()) {
744
+ return xs
745
+ }
746
+ let n: i32 = 0
747
+ while (this.nextElement()) {
748
+ let cur: string = ""
749
+ if (n < toI32(xs.length)) {
750
+ cur = xs[n]
751
+ }
752
+ // Read into a local first: the call ends what the guard proved about `n`.
753
+ const v: string = this.string(cur)
754
+ if (n < toI32(xs.length)) {
755
+ xs[n] = v
756
+ } else {
757
+ xs.push(v)
758
+ }
759
+ n += 1
760
+ }
761
+ while (toI32(xs.length) > n && xs.length > 0) {
762
+ xs.pop()
763
+ }
764
+ return xs
765
+ }
766
+
767
+ i32ArrayOrNull(xs: i32[] | null): i32[] | null {
768
+ if (this.takeNull()) {
769
+ return null
770
+ }
771
+ if (xs !== null) {
772
+ return this.i32Array(xs)
773
+ }
774
+ const fresh: i32[] = []
775
+ return this.i32Array(fresh)
776
+ }
777
+
778
+ u32ArrayOrNull(xs: u32[] | null): u32[] | null {
779
+ if (this.takeNull()) {
780
+ return null
781
+ }
782
+ if (xs !== null) {
783
+ return this.u32Array(xs)
784
+ }
785
+ const fresh: u32[] = []
786
+ return this.u32Array(fresh)
787
+ }
788
+
789
+ i64ArrayOrNull(xs: i64[] | null): i64[] | null {
790
+ if (this.takeNull()) {
791
+ return null
792
+ }
793
+ if (xs !== null) {
794
+ return this.i64Array(xs)
795
+ }
796
+ const fresh: i64[] = []
797
+ return this.i64Array(fresh)
798
+ }
799
+
800
+ u64ArrayOrNull(xs: u64[] | null): u64[] | null {
801
+ if (this.takeNull()) {
802
+ return null
803
+ }
804
+ if (xs !== null) {
805
+ return this.u64Array(xs)
806
+ }
807
+ const fresh: u64[] = []
808
+ return this.u64Array(fresh)
809
+ }
810
+
811
+ f64ArrayOrNull(xs: f64[] | null): f64[] | null {
812
+ if (this.takeNull()) {
813
+ return null
814
+ }
815
+ if (xs !== null) {
816
+ return this.f64Array(xs)
817
+ }
818
+ const fresh: f64[] = []
819
+ return this.f64Array(fresh)
820
+ }
821
+
822
+ booleanArrayOrNull(xs: boolean[] | null): boolean[] | null {
823
+ if (this.takeNull()) {
824
+ return null
825
+ }
826
+ if (xs !== null) {
827
+ return this.booleanArray(xs)
828
+ }
829
+ const fresh: boolean[] = []
830
+ return this.booleanArray(fresh)
831
+ }
832
+
833
+ stringArrayOrNull(xs: string[] | null): string[] | null {
834
+ if (this.takeNull()) {
835
+ return null
836
+ }
837
+ if (xs !== null) {
838
+ return this.stringArray(xs)
839
+ }
840
+ const fresh: string[] = []
841
+ return this.stringArray(fresh)
842
+ }
843
+ }
844
+
845
+ /**
846
+ * Decodes the JSON object `d` holds into `out`, the whole input, and answers
847
+ * `d.failed`: `0`, or the first error's code. The compiler writes the code
848
+ * from `T`'s fields at every call; this body is what Node runs.
849
+ */
850
+ export const jsonDecode = <T>(_d: JsonDecoder, _out: T): i32 => {
851
+ panic(JSON_TYPED_ERASED)
852
+ }
853
+
854
+ /**
855
+ * Writes `value` to `w` as one JSON object, its fields in declaration order.
856
+ * The compiler writes the code from `T`'s fields at every call; this body is
857
+ * what Node runs.
858
+ */
859
+ export const jsonEncode = <T>(_w: JsonWriter, _value: T): void => {
860
+ panic(JSON_TYPED_ERASED)
861
+ }
862
+
863
+ // What an encoding calls for a field that is not one writer call. Exported
864
+ // because the code the compiler writes calls them from the module that
865
+ // encodes, which may not be this one.
866
+
867
+ export const jsonEncodeStringOrNull = (w: JsonWriter, s: string | null): void => {
868
+ if (s === null) {
869
+ w.nullValue()
870
+ } else {
871
+ w.string(s)
872
+ }
873
+ }
874
+
875
+ /**
876
+ * A `u64`, as its digits: at most 20 of them, written with `raw` from an
877
+ * array of this call's own that nothing keeps. A value past 2^63 has no
878
+ * `i64` to go through the writer's `i64` as, so every `u64` takes this one
879
+ * loop. Every `u64` here is built with `toU64`, a BigInt under Node.
880
+ */
881
+ export const jsonEncodeU64 = (w: JsonWriter, v: u64): void => {
882
+ const ten: u64 = toU64(10)
883
+ const zero: u64 = toU64(0)
884
+ const digits: u8[] = new Array<u8>(20)
885
+ let rest: u64 = v
886
+ let first: i32 = toI32(digits.length)
887
+ for (let k: i32 = first - 1; k >= 0 && k < toI32(digits.length); k -= 1) {
888
+ digits[k] = toU8(48 + toI32(rest % ten))
889
+ rest = rest / ten
890
+ first = k
891
+ if (rest === zero) {
892
+ break
893
+ }
894
+ }
895
+ w.raw(digits, first, toI32(digits.length) - first)
896
+ }
897
+
898
+ /** A `JsonNumber`, as the text it holds, byte for byte. */
899
+ export const jsonEncodeNumber = (w: JsonWriter, n: JsonNumber): void => {
900
+ const start: i32 = 0
901
+ w.raw(n.bytes, start, n.count)
902
+ }
903
+
904
+ export const jsonEncodeI32Array = (w: JsonWriter, xs: i32[]): void => {
905
+ w.beginArray()
906
+ for (const x of xs) {
907
+ w.i32(x)
908
+ }
909
+ w.endArray()
910
+ }
911
+
912
+ export const jsonEncodeU32Array = (w: JsonWriter, xs: u32[]): void => {
913
+ w.beginArray()
914
+ for (const x of xs) {
915
+ w.u32(x)
916
+ }
917
+ w.endArray()
918
+ }
919
+
920
+ export const jsonEncodeI64Array = (w: JsonWriter, xs: i64[]): void => {
921
+ w.beginArray()
922
+ for (const x of xs) {
923
+ w.i64(x)
924
+ }
925
+ w.endArray()
926
+ }
927
+
928
+ export const jsonEncodeU64Array = (w: JsonWriter, xs: u64[]): void => {
929
+ w.beginArray()
930
+ for (const x of xs) {
931
+ jsonEncodeU64(w, x)
932
+ }
933
+ w.endArray()
934
+ }
935
+
936
+ export const jsonEncodeF64Array = (w: JsonWriter, xs: f64[]): void => {
937
+ w.beginArray()
938
+ for (const x of xs) {
939
+ w.f64(x)
940
+ }
941
+ w.endArray()
942
+ }
943
+
944
+ export const jsonEncodeBooleanArray = (w: JsonWriter, xs: boolean[]): void => {
945
+ w.beginArray()
946
+ for (const x of xs) {
947
+ w.boolean(x)
948
+ }
949
+ w.endArray()
950
+ }
951
+
952
+ export const jsonEncodeStringArray = (w: JsonWriter, xs: string[]): void => {
953
+ w.beginArray()
954
+ for (const x of xs) {
955
+ w.string(x)
956
+ }
957
+ w.endArray()
958
+ }
959
+
960
+ export const jsonEncodeI32ArrayOrNull = (w: JsonWriter, xs: i32[] | null): void => {
961
+ if (xs === null) {
962
+ w.nullValue()
963
+ } else {
964
+ jsonEncodeI32Array(w, xs)
965
+ }
966
+ }
967
+
968
+ export const jsonEncodeU32ArrayOrNull = (w: JsonWriter, xs: u32[] | null): void => {
969
+ if (xs === null) {
970
+ w.nullValue()
971
+ } else {
972
+ jsonEncodeU32Array(w, xs)
973
+ }
974
+ }
975
+
976
+ export const jsonEncodeI64ArrayOrNull = (w: JsonWriter, xs: i64[] | null): void => {
977
+ if (xs === null) {
978
+ w.nullValue()
979
+ } else {
980
+ jsonEncodeI64Array(w, xs)
981
+ }
982
+ }
983
+
984
+ export const jsonEncodeU64ArrayOrNull = (w: JsonWriter, xs: u64[] | null): void => {
985
+ if (xs === null) {
986
+ w.nullValue()
987
+ } else {
988
+ jsonEncodeU64Array(w, xs)
989
+ }
990
+ }
991
+
992
+ export const jsonEncodeF64ArrayOrNull = (w: JsonWriter, xs: f64[] | null): void => {
993
+ if (xs === null) {
994
+ w.nullValue()
995
+ } else {
996
+ jsonEncodeF64Array(w, xs)
997
+ }
998
+ }
999
+
1000
+ export const jsonEncodeBooleanArrayOrNull = (w: JsonWriter, xs: boolean[] | null): void => {
1001
+ if (xs === null) {
1002
+ w.nullValue()
1003
+ } else {
1004
+ jsonEncodeBooleanArray(w, xs)
1005
+ }
1006
+ }
1007
+
1008
+ export const jsonEncodeStringArrayOrNull = (w: JsonWriter, xs: string[] | null): void => {
1009
+ if (xs === null) {
1010
+ w.nullValue()
1011
+ } else {
1012
+ jsonEncodeStringArray(w, xs)
1013
+ }
1014
+ }