@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
package/std/base64.ts ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * `nish/base64` — standard base64 (RFC 4648 §4) with `=` padding, the encoding
3
+ * kitty graphics frames are sent in.
4
+ *
5
+ * The alphabet is `A-Z a-z 0-9 + /`. Every three bytes become four characters,
6
+ * and a final group of one or two bytes becomes two or three characters filled
7
+ * out to four with `=` (RFC 4648 §4, the padding rules of §3.2), so the text is
8
+ * always a multiple of four long.
9
+ *
10
+ * - `base64EncodedLength(n)` is the characters `n` bytes encode to.
11
+ * - `base64EncodeInto(src, off, len, dst, at)` writes the encoding of
12
+ * `src[off..off+len)` into `dst` from `at` and allocates nothing, so a frame
13
+ * can be encoded chunk by chunk straight into its output buffer.
14
+ * - `base64Encode(bytes)` is the whole array as a string.
15
+ *
16
+ * This module only encodes: what it is for writes base64 and never reads it
17
+ * back. It is not the strict decoder of `nish/crypto/base64url`, which is a
18
+ * different alphabet without padding and is written not to branch on the data;
19
+ * what goes through here is pixels, not secrets, so a sextet becomes its
20
+ * character by indexing the alphabet. The output is ASCII, so the string is
21
+ * the same bytes natively and under Node.
22
+ *
23
+ * Private helpers share the importing program's flat symbol namespace
24
+ * (`docs/wp26-stdlib.md` §3e), which is why each one carries the module's name.
25
+ */
26
+
27
+ /** The 64 characters of RFC 4648 §4's Table 1, in value order. */
28
+ const BASE64_ALPHABET: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
29
+
30
+ /** `=`, which fills a short final group out to four characters (RFC 4648 §3.2). */
31
+ const BASE64_PAD: i32 = 61
32
+
33
+ /**
34
+ * The characters `n` bytes encode to: four for every three, a short final
35
+ * group counted as a whole one. Panics when `n` is negative or the length
36
+ * would pass 2^31 - 1, which `n` above 1,610,612,733 does.
37
+ */
38
+ export const base64EncodedLength = (n: i32): i32 => {
39
+ if (n < 0) {
40
+ panic("base64EncodedLength: a negative byte count")
41
+ }
42
+ // (2^31 - 1) / 4 * 3 groups' worth of bytes is the most whose encoding fits.
43
+ if (n > 1610612733) {
44
+ panic("base64EncodedLength: the encoding is longer than 2^31 - 1 characters")
45
+ }
46
+ return (((n + 2) / 3) | 0) * 4
47
+ }
48
+
49
+ /** The byte of the character for the sextet `v` (`0 <= v <= 63`). */
50
+ const base64CharOf = (v: i32): u8 => toU8(BASE64_ALPHABET.charCodeAt(v))
51
+
52
+ /**
53
+ * Write the base64 of `src[off..off+len)` into `dst` from index `at`, and
54
+ * answer the index just past the last character written, which is
55
+ * `at + base64EncodedLength(len)`. Nothing is allocated. Panics when the source
56
+ * range is not inside `src` or the encoding does not fit in `dst` from `at`;
57
+ * both are checked before anything is written.
58
+ */
59
+ export const base64EncodeInto = (src: u8[], off: i32, len: i32, dst: u8[], at: i32): i32 => {
60
+ // Refused before `toI32`, which saturates a longer length under
61
+ // `--number-mode f64` and would let a range past the true end through.
62
+ if (src.length > 2147483647 || dst.length > 2147483647) {
63
+ panic("base64EncodeInto: an array longer than 2^31 - 1 bytes")
64
+ }
65
+ const srcLength: i32 = toI32(src.length)
66
+ const dstLength: i32 = toI32(dst.length)
67
+ if (off < 0 || len < 0 || off > srcLength - len) {
68
+ panic("base64EncodeInto: the source range is outside the array")
69
+ }
70
+ const need: i32 = base64EncodedLength(len)
71
+ if (at < 0 || at > dstLength - need) {
72
+ panic("base64EncodeInto: the encoding does not fit in the destination")
73
+ }
74
+ let i: i32 = off
75
+ let o: i32 = at
76
+ const whole: i32 = off + len - (len % 3)
77
+ // The checks above make every term after the first true; they are written out
78
+ // because they are what proves the loop's accesses in range.
79
+ while (i < whole && i >= 0 && i + 2 < srcLength && o >= 0 && o + 3 < dstLength) {
80
+ const group: i32 = (toI32(src[i]) << 16) | (toI32(src[i + 1]) << 8) | toI32(src[i + 2])
81
+ dst[o] = base64CharOf(group >> 18)
82
+ dst[o + 1] = base64CharOf((group >> 12) & 63)
83
+ dst[o + 2] = base64CharOf((group >> 6) & 63)
84
+ dst[o + 3] = base64CharOf(group & 63)
85
+ i = i + 3
86
+ o = o + 4
87
+ }
88
+ const tail: i32 = len % 3
89
+ if (tail === 1) {
90
+ const group: i32 = toI32(src[i]) << 16
91
+ dst[o] = base64CharOf(group >> 18)
92
+ dst[o + 1] = base64CharOf((group >> 12) & 63)
93
+ dst[o + 2] = toU8(BASE64_PAD)
94
+ dst[o + 3] = toU8(BASE64_PAD)
95
+ o = o + 4
96
+ } else if (tail === 2) {
97
+ const group: i32 = (toI32(src[i]) << 16) | (toI32(src[i + 1]) << 8)
98
+ dst[o] = base64CharOf(group >> 18)
99
+ dst[o + 1] = base64CharOf((group >> 12) & 63)
100
+ dst[o + 2] = base64CharOf((group >> 6) & 63)
101
+ dst[o + 3] = toU8(BASE64_PAD)
102
+ o = o + 4
103
+ }
104
+ return o
105
+ }
106
+
107
+ /** `bytes` as padded base64. Panics past 1,610,612,733 bytes, whose encoding would not fit a string. */
108
+ export const base64Encode = (bytes: u8[]): string => {
109
+ if (bytes.length > 2147483647) {
110
+ panic("base64Encode: more than 2^31 - 1 bytes")
111
+ }
112
+ const n: i32 = toI32(bytes.length)
113
+ const out: u8[] = new Array<u8>(base64EncodedLength(n))
114
+ const end: i32 = base64EncodeInto(bytes, 0, n, out, 0)
115
+ return String.fromBytes(out, 0, end)
116
+ }
package/std/bytes.ts ADDED
@@ -0,0 +1,419 @@
1
+ /**
2
+ * `std/bytes` — fixed-width integers and doubles read from, and written into,
3
+ * a byte array at an offset, in either byte order.
4
+ *
5
+ * A wire format, a file header or a hash's message schedule is a `u8[]` with
6
+ * numbers laid out in it, and every reader of one writes the same four-line
7
+ * shift-and-or. This module is that loop written once:
8
+ *
9
+ * import { getU32BE, setU16LE } from "nish/bytes";
10
+ *
11
+ * const header: u8[] = [0, 0, 1, 0, 0, 0];
12
+ * const length = getU32BE(header, 0); // 256
13
+ * setU16LE(header, 4, toU16(513)); // header[4] = 1, header[5] = 2
14
+ *
15
+ * Every function takes the array and the offset of its first byte; the `LE`
16
+ * name puts the least significant byte there, the `BE` name the most
17
+ * significant. The widths are `u16`, `u32` and `u64`, the signed `i32` and
18
+ * `i64`, which are the same bytes read as two's complement, and `f64`, whose
19
+ * bytes are its IEEE 754 bits (`f64ToBits`). There is no `f32`: the language
20
+ * has no bit cast for one.
21
+ *
22
+ * Each access is an ordinary index, so an offset whose bytes do not all lie in
23
+ * the array panics `index`, naming the first byte that does not. A guard in
24
+ * the caller does not yet remove these checks: in a loop guarded by
25
+ * `off + 3 < b.length`, the checker proves an index it can see but not one
26
+ * inside a call, and after `getU32LE` inlines, LLVM keeps the checks on
27
+ * `off + 1` to `off + 3`, because the guard compares the length truncated to
28
+ * `i32` and the checks compare it unsigned at 64 bits. A loop that needs them
29
+ * gone indexes the bytes itself.
30
+ *
31
+ * The in-range answers are byte for byte those of the copies `std/` keeps for
32
+ * itself: `sha256LoadWord` (`std/crypto/sha256.ts`) for `getU32BE`,
33
+ * `chacha20Word` and `poly1305Le64` (`std/crypto/chacha20poly1305.ts`) for
34
+ * `getU32LE` and `getU64LE`, `loadWord` and `storeWord` (`std/crypto/sha512.ts`)
35
+ * for `getU64BE` and `setU64BE`, `http2FramePut32` (`std/net/http2-frame.ts`)
36
+ * for `setU32BE`, and `tlsPutU16` (`std/net/tls/codec.ts`) for `setU16BE`. None
37
+ * of them is replaced by this module. Out of range they differ: the AES and
38
+ * TLS word helpers read zero past the end and drop bytes written there, which
39
+ * their callers rely on, where this module panics.
40
+ *
41
+ * Under Node (`docs/RUN_UNDER_NODE.md`) the `u16` and `u32` functions are
42
+ * expected to answer as they do natively, because the top byte of a `u32` is
43
+ * multiplied in rather than shifted and each byte written is masked before
44
+ * its `toU8`: there `<<` turns bit 31 into a sign and the prelude's `toU8`
45
+ * and `toU32` saturate, and natively the multiply and the mask fold into the
46
+ * shift and the truncation. The others do not yet answer there: the `i32`
47
+ * functions cross between signed and unsigned with `toI32` and `toU32`, which
48
+ * the prelude saturates too (`setI32LE(b, 0, -2)` writes zeros), and the
49
+ * 64-bit functions and `f64` meet its BigInt `u64` and `i64`, which `toU8`
50
+ * refuses.
51
+ *
52
+ * The module also has the runs a parser walks and the copy it makes of them.
53
+ * `skipBlank`, `skipDigits`, `skipJsonText` and `skipJsonPlain` each answer
54
+ * the first index in a range whose byte is not in their class — JSON's blanks,
55
+ * the ASCII digits, the bytes a JSON string holds as themselves, the bytes a
56
+ * JSON writer copies without an escape — and `copyBytes` copies a
57
+ * window of one array into another, or into itself, as one move:
58
+ *
59
+ * const text: u8[] = [32, 32, 52, 50, 44]; // " 42,"
60
+ * const start = skipBlank(text, 0, 5); // 2
61
+ * const end = skipDigits(text, start, 5); // 4
62
+ *
63
+ * The four runs clamp their range and never panic; `copyBytes` panics on a
64
+ * range outside its array. Natively each is a runtime kernel
65
+ * (docs/LANGUAGE.md, "Byte runs"), and the runs are variable-time: they are
66
+ * for text, never for secret data.
67
+ */
68
+
69
+ /** The `u16` whose low byte is `b[off]` and high byte `b[off + 1]`. */
70
+ export const getU16LE = (b: u8[], off: i32): u16 => toU16(b[off]) | (toU16(b[off + 1]) << 8)
71
+
72
+ /** The `u16` whose high byte is `b[off]` and low byte `b[off + 1]`. */
73
+ export const getU16BE = (b: u8[], off: i32): u16 => (toU16(b[off]) << 8) | toU16(b[off + 1])
74
+
75
+ /** The `u32` whose bytes, least significant first, are `b[off]` to `b[off + 3]`. */
76
+ export const getU32LE = (b: u8[], off: i32): u32 =>
77
+ (toU32(b[off]) | (toU32(b[off + 1]) << 8) | (toU32(b[off + 2]) << 16)) +
78
+ toU32(b[off + 3]) * toU32(0x1000000)
79
+
80
+ /** The `u32` whose bytes, most significant first, are `b[off]` to `b[off + 3]`. */
81
+ export const getU32BE = (b: u8[], off: i32): u32 =>
82
+ toU32(b[off]) * toU32(0x1000000) +
83
+ ((toU32(b[off + 1]) << 16) | (toU32(b[off + 2]) << 8) | toU32(b[off + 3]))
84
+
85
+ /** The `u64` whose bytes, least significant first, are `b[off]` to `b[off + 7]`. */
86
+ export const getU64LE = (b: u8[], off: i32): u64 => {
87
+ let v = toU64(0)
88
+ for (let i: i32 = 0; i < 8; i++) {
89
+ v = v | (toU64(b[off + i]) << toU64(i * 8))
90
+ }
91
+ return v
92
+ }
93
+
94
+ /** The `u64` whose bytes, most significant first, are `b[off]` to `b[off + 7]`. */
95
+ export const getU64BE = (b: u8[], off: i32): u64 => {
96
+ let v = toU64(0)
97
+ for (let i: i32 = 0; i < 8; i++) {
98
+ v = (v << toU64(8)) | toU64(b[off + i])
99
+ }
100
+ return v
101
+ }
102
+
103
+ /** `getU32LE`'s bits as a two's-complement `i32`. */
104
+ export const getI32LE = (b: u8[], off: i32): i32 => toI32(getU32LE(b, off))
105
+
106
+ /** `getU32BE`'s bits as a two's-complement `i32`. */
107
+ export const getI32BE = (b: u8[], off: i32): i32 => toI32(getU32BE(b, off))
108
+
109
+ /** `getU64LE`'s bits as a two's-complement `i64`. */
110
+ export const getI64LE = (b: u8[], off: i32): i64 => toI64(getU64LE(b, off))
111
+
112
+ /** `getU64BE`'s bits as a two's-complement `i64`. */
113
+ export const getI64BE = (b: u8[], off: i32): i64 => toI64(getU64BE(b, off))
114
+
115
+ /** The `f64` whose IEEE 754 bits are `getU64LE`'s. */
116
+ export const getF64LE = (b: u8[], off: i32): f64 => bitsToF64(toI64(getU64LE(b, off)))
117
+
118
+ /** The `f64` whose IEEE 754 bits are `getU64BE`'s. */
119
+ export const getF64BE = (b: u8[], off: i32): f64 => bitsToF64(toI64(getU64BE(b, off)))
120
+
121
+ /** Writes `v` into `b[off]` and `b[off + 1]`, low byte first. */
122
+ export const setU16LE = (b: u8[], off: i32, v: u16): void => {
123
+ b[off] = toU8(v & 255)
124
+ b[off + 1] = toU8((v >> 8) & 255)
125
+ }
126
+
127
+ /** Writes `v` into `b[off]` and `b[off + 1]`, high byte first. */
128
+ export const setU16BE = (b: u8[], off: i32, v: u16): void => {
129
+ b[off] = toU8((v >> 8) & 255)
130
+ b[off + 1] = toU8(v & 255)
131
+ }
132
+
133
+ /** Writes `v` into `b[off]` to `b[off + 3]`, least significant byte first. */
134
+ export const setU32LE = (b: u8[], off: i32, v: u32): void => {
135
+ b[off] = toU8(v & 255)
136
+ b[off + 1] = toU8((v >> 8) & 255)
137
+ b[off + 2] = toU8((v >> 16) & 255)
138
+ b[off + 3] = toU8((v >> 24) & 255)
139
+ }
140
+
141
+ /** Writes `v` into `b[off]` to `b[off + 3]`, most significant byte first. */
142
+ export const setU32BE = (b: u8[], off: i32, v: u32): void => {
143
+ b[off] = toU8((v >> 24) & 255)
144
+ b[off + 1] = toU8((v >> 16) & 255)
145
+ b[off + 2] = toU8((v >> 8) & 255)
146
+ b[off + 3] = toU8(v & 255)
147
+ }
148
+
149
+ /** Writes `v` into `b[off]` to `b[off + 7]`, least significant byte first. */
150
+ export const setU64LE = (b: u8[], off: i32, v: u64): void => {
151
+ for (let i: i32 = 0; i < 8; i++) {
152
+ b[off + i] = toU8((v >> toU64(i * 8)) & toU64(255))
153
+ }
154
+ }
155
+
156
+ /** Writes `v` into `b[off]` to `b[off + 7]`, most significant byte first. */
157
+ export const setU64BE = (b: u8[], off: i32, v: u64): void => {
158
+ for (let i: i32 = 0; i < 8; i++) {
159
+ b[off + i] = toU8((v >> toU64((7 - i) * 8)) & toU64(255))
160
+ }
161
+ }
162
+
163
+ /** Writes `v`'s two's-complement bits as `setU32LE` does. */
164
+ export const setI32LE = (b: u8[], off: i32, v: i32): void => setU32LE(b, off, toU32(v))
165
+
166
+ /** Writes `v`'s two's-complement bits as `setU32BE` does. */
167
+ export const setI32BE = (b: u8[], off: i32, v: i32): void => setU32BE(b, off, toU32(v))
168
+
169
+ /** Writes `v`'s two's-complement bits as `setU64LE` does. */
170
+ export const setI64LE = (b: u8[], off: i32, v: i64): void => setU64LE(b, off, toU64(v))
171
+
172
+ /** Writes `v`'s two's-complement bits as `setU64BE` does. */
173
+ export const setI64BE = (b: u8[], off: i32, v: i64): void => setU64BE(b, off, toU64(v))
174
+
175
+ /** Writes `v`'s IEEE 754 bits as `setU64LE` does. */
176
+ export const setF64LE = (b: u8[], off: i32, v: f64): void => setU64LE(b, off, toU64(f64ToBits(v)))
177
+
178
+ /** Writes `v`'s IEEE 754 bits as `setU64BE` does. */
179
+ export const setF64BE = (b: u8[], off: i32, v: f64): void => setU64BE(b, off, toU64(f64ToBits(v)))
180
+
181
+ // ---- Byte-class runs and the byte copy (WP38 S6a) ----------------------------------------
182
+
183
+ /** JSON's four blanks (RFC 8259 §2): space, tab, newline and carriage return. */
184
+ const BYTES_SPACE: i32 = 32
185
+ const BYTES_TAB: i32 = 9
186
+ const BYTES_NEWLINE: i32 = 10
187
+ const BYTES_CARRIAGE_RETURN: i32 = 13
188
+ /** `0` and `9`. */
189
+ const BYTES_DIGIT_ZERO: i32 = 48
190
+ const BYTES_DIGIT_NINE: i32 = 57
191
+ /** The two printable ASCII bytes a JSON string escapes, `"` and `\`. */
192
+ const BYTES_QUOTE: i32 = 34
193
+ const BYTES_BACKSLASH: i32 = 92
194
+ /** The first byte that is not ASCII, and the continuation bytes' range. */
195
+ const BYTES_NON_ASCII: i32 = 128
196
+ const BYTES_CONTINUATION_TOP: i32 = 191
197
+
198
+ /** `to` clamped into `[0, b.length]`: where a run's scan stops. */
199
+ const bytesRunEnd = (b: u8[], to: i32): i32 => {
200
+ const n: i32 = toI32(b.length)
201
+ if (to < 0) {
202
+ return 0
203
+ }
204
+ return to < n ? to : n
205
+ }
206
+
207
+ /** `from` clamped into `[0, end]`: where a run's scan starts. */
208
+ const bytesRunStart = (from: i32, end: i32): i32 => {
209
+ if (from < 0) {
210
+ return 0
211
+ }
212
+ return from < end ? from : end
213
+ }
214
+
215
+ /**
216
+ * The first index in `[from, to)` whose byte is not one of JSON's blanks —
217
+ * space, tab, newline, carriage return — or `to` when every byte there is
218
+ * one. `to` is clamped to `[0, b.length]` and `from` to `[0, to]`, as
219
+ * `indexOfAny` clamps, so no range panics: one past the end answers the end.
220
+ *
221
+ * Natively the scan is the runtime's `nish_bytes_skip_blank`, which reads 16
222
+ * or 32 bytes at a time (docs/LANGUAGE.md, "Byte runs"). It is
223
+ * **variable-time**: how long it takes says how long the run is, so it is
224
+ * never for secret data.
225
+ */
226
+ export const skipBlank = (b: u8[], from: i32, to: i32): i32 => {
227
+ const end: i32 = bytesRunEnd(b, to)
228
+ return skipBlankWalk(b, bytesRunStart(from, end), end)
229
+ }
230
+
231
+ /** `skipBlank` for the ASCII digits `0` to `9`: the same clamps, the same kernel family, `nish_bytes_skip_digits`. */
232
+ export const skipDigits = (b: u8[], from: i32, to: i32): i32 => {
233
+ const end: i32 = bytesRunEnd(b, to)
234
+ return skipDigitsWalk(b, bytesRunStart(from, end), end)
235
+ }
236
+
237
+ /**
238
+ * `skipBlank` for the bytes a JSON string holds as themselves: printable ASCII
239
+ * other than `"` and `\`, and every well-formed UTF-8 sequence (RFC 3629 §4)
240
+ * that ends before `to`. The run stops at the first quote, backslash or
241
+ * control byte, and at the lead byte of a sequence that is malformed — an
242
+ * overlong form, a surrogate, a code point past U+10FFFF, a stray continuation
243
+ * byte — or cut short by `to`. So a whole JSON string body with no escape is
244
+ * one call, and where it stops is the byte a decoder has to look at. Natively
245
+ * the scan is `nish_bytes_skip_json_text`: blocks of ASCII 16 or 32 bytes at a
246
+ * time, each multi-byte sequence a byte at a time. Variable-time, as
247
+ * `skipBlank` is.
248
+ */
249
+ export const skipJsonText = (b: u8[], from: i32, to: i32): i32 => {
250
+ const end: i32 = bytesRunEnd(b, to)
251
+ return skipJsonTextWalk(b, bytesRunStart(from, end), end)
252
+ }
253
+
254
+ /**
255
+ * The first index in `[from, to)` whose byte a JSON writer cannot copy as
256
+ * itself — a control byte below `0x20`, a quote or a backslash — or `to`, with
257
+ * the range clamped as `skipBlank`'s is. Every byte from `0x20` up is in the
258
+ * run, `0x7f` and the bytes from `0x80` up included, and no UTF-8 is checked:
259
+ * where `skipJsonText` is the reader's run, this is the writer's, which passes
260
+ * the bytes of a string through as they are. Natively the scan is
261
+ * `nish_bytes_skip_json_plain`, 16 bytes at a time. Variable-time, as
262
+ * `skipBlank` is.
263
+ */
264
+ export const skipJsonPlain = (b: u8[], from: i32, to: i32): i32 => {
265
+ const end: i32 = bytesRunEnd(b, to)
266
+ return skipJsonPlainWalk(b, bytesRunStart(from, end), end)
267
+ }
268
+
269
+ /**
270
+ * `count` bytes of `src` from `from` written over `dst` from `at`, as one
271
+ * copy: where `dst` and `src` are one array and the two ranges overlap, the
272
+ * bytes land as if every one were read before any was written, as
273
+ * `copyWithin` promises. Where `dst.set(src, at)` copies all of `src`, this
274
+ * copies a window of it, and allocates nothing.
275
+ *
276
+ * A negative `count`, or a range that does not lie inside its array —
277
+ * `0 <= from <= from + count <= src.length` and the same for `at` in `dst` —
278
+ * panics `copyBytes` before any byte is written. Natively the copy is one
279
+ * `llvm.memmove`.
280
+ */
281
+ export const copyBytes = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
282
+ if (count < 0 || at < 0 || from < 0 || at > toI32(dst.length) - count || from > toI32(src.length) - count) {
283
+ panic("copyBytes: the range lies outside an array")
284
+ }
285
+ copyBytesWalk(dst, at, src, from, count)
286
+ }
287
+
288
+ /**
289
+ * `skipBlank`'s walk, once its range is clamped. This loop and the four
290
+ * below are what run under Node; natively the compiler replaces the one call
291
+ * each public function makes with the runtime kernel (`src/kernels.ts`), as it
292
+ * does `indexOfAny`'s walk, so each loop is its kernel's meaning written in
293
+ * the language. The `i < b.length` test never fails after the clamp; it is
294
+ * written because it is what proves the index.
295
+ */
296
+ const skipBlankWalk = (b: u8[], from: i32, to: i32): i32 => {
297
+ let i: i32 = from
298
+ while (i >= 0 && i < to && i < toI32(b.length)) {
299
+ const c: i32 = toI32(b[i])
300
+ if (c !== BYTES_SPACE && c !== BYTES_TAB && c !== BYTES_NEWLINE && c !== BYTES_CARRIAGE_RETURN) {
301
+ return i
302
+ }
303
+ i += 1
304
+ }
305
+ return i
306
+ }
307
+
308
+ /** `skipDigits`'s walk, once its range is clamped. */
309
+ const skipDigitsWalk = (b: u8[], from: i32, to: i32): i32 => {
310
+ let i: i32 = from
311
+ while (i >= 0 && i < to && i < toI32(b.length)) {
312
+ const c: i32 = toI32(b[i])
313
+ if (c < BYTES_DIGIT_ZERO || c > BYTES_DIGIT_NINE) {
314
+ return i
315
+ }
316
+ i += 1
317
+ }
318
+ return i
319
+ }
320
+
321
+ /**
322
+ * The length of the well-formed UTF-8 sequence whose lead byte is `b[i]` and
323
+ * that ends at or before `to`, or 0: RFC 3629's table, with the narrowed
324
+ * second byte after `E0`, `ED`, `F0` and `F4`.
325
+ */
326
+ const bytesUtf8Length = (b: u8[], i: i32, to: i32): i32 => {
327
+ const lead: i32 = toI32(b[i])
328
+ let low: i32 = BYTES_NON_ASCII
329
+ let high: i32 = BYTES_CONTINUATION_TOP
330
+ let n: i32 = 0
331
+ if (lead >= 0xc2 && lead <= 0xdf) {
332
+ n = 2
333
+ } else if (lead >= 0xe0 && lead <= 0xef) {
334
+ n = 3
335
+ if (lead === 0xe0) {
336
+ low = 0xa0
337
+ }
338
+ if (lead === 0xed) {
339
+ high = 0x9f
340
+ }
341
+ } else if (lead >= 0xf0 && lead <= 0xf4) {
342
+ n = 4
343
+ if (lead === 0xf0) {
344
+ low = 0x90
345
+ }
346
+ if (lead === 0xf4) {
347
+ high = 0x8f
348
+ }
349
+ } else {
350
+ return 0
351
+ }
352
+ if (to - i < n) {
353
+ return 0
354
+ }
355
+ const second: i32 = toI32(b[i + 1])
356
+ if (second < low || second > high) {
357
+ return 0
358
+ }
359
+ let k: i32 = 2
360
+ while (k < n) {
361
+ const c: i32 = toI32(b[i + k])
362
+ if (c < BYTES_NON_ASCII || c > BYTES_CONTINUATION_TOP) {
363
+ return 0
364
+ }
365
+ k += 1
366
+ }
367
+ return n
368
+ }
369
+
370
+ /** `skipJsonText`'s walk, once its range is clamped. */
371
+ const skipJsonTextWalk = (b: u8[], from: i32, to: i32): i32 => {
372
+ let i: i32 = from
373
+ while (i >= 0 && i < to && i < toI32(b.length)) {
374
+ const c: i32 = toI32(b[i])
375
+ if (c >= BYTES_NON_ASCII) {
376
+ const n: i32 = bytesUtf8Length(b, i, to)
377
+ if (n === 0) {
378
+ return i
379
+ }
380
+ i += n
381
+ continue
382
+ }
383
+ if (c < BYTES_SPACE || c === BYTES_QUOTE || c === BYTES_BACKSLASH) {
384
+ return i
385
+ }
386
+ i += 1
387
+ }
388
+ return i
389
+ }
390
+
391
+ /** `skipJsonPlain`'s walk, once its range is clamped. */
392
+ const skipJsonPlainWalk = (b: u8[], from: i32, to: i32): i32 => {
393
+ let i: i32 = from
394
+ while (i >= 0 && i < to && i < toI32(b.length)) {
395
+ const c: i32 = toI32(b[i])
396
+ if (c < BYTES_SPACE || c === BYTES_QUOTE || c === BYTES_BACKSLASH) {
397
+ return i
398
+ }
399
+ i += 1
400
+ }
401
+ return i
402
+ }
403
+
404
+ /** `copyBytes`'s walk, once its ranges are checked: forward, or backward when `dst` is `src` and the bytes move up. */
405
+ const copyBytesWalk = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
406
+ if (at <= from) {
407
+ let k: i32 = 0
408
+ while (k < count) {
409
+ dst[at + k] = src[from + k]
410
+ k += 1
411
+ }
412
+ return
413
+ }
414
+ let k: i32 = count - 1
415
+ while (k >= 0) {
416
+ dst[at + k] = src[from + k]
417
+ k -= 1
418
+ }
419
+ }