@amritk/nish-x86_64-linux 0.23.1 → 0.25.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 (51) hide show
  1. package/bin/nish +0 -0
  2. package/docs/AI.md +50 -23
  3. package/package.json +1 -1
  4. package/runtime/browser.mjs +4 -3
  5. package/runtime/core/arrays.d.ts +0 -2
  6. package/runtime/core/arrays.mjs +0 -2
  7. package/runtime/core/host.d.ts +8 -0
  8. package/runtime/core/host.mjs +50 -2
  9. package/runtime/core/numbers.mjs +2 -3
  10. package/runtime/nish.d.ts +100 -4
  11. package/runtime/nish.h +34 -0
  12. package/runtime/nish.mjs +23 -5
  13. package/runtime/node.mjs +57 -6
  14. package/runtime/runtime-net.c +45 -4
  15. package/runtime/runtime-os.c +115 -12
  16. package/runtime/runtime-term.c +2 -2
  17. package/runtime/runtime.c +1 -1
  18. package/scripts/build.sh +13 -3
  19. package/std/README.md +44 -7
  20. package/std/cli-args.ts +1216 -0
  21. package/std/cli-flags.ts +585 -0
  22. package/std/cli.ts +308 -19
  23. package/std/compress/checksum.ts +290 -0
  24. package/std/compress/deflate.ts +2790 -0
  25. package/std/compress/gzip.ts +761 -0
  26. package/std/compress/zlib.ts +168 -0
  27. package/std/crypto/LICENSE-fiat-crypto-p384 +21 -0
  28. package/std/crypto/p256.ts +63 -1
  29. package/std/crypto/p384.ts +6044 -0
  30. package/std/crypto/pki-roots.ts +322 -0
  31. package/std/crypto/pki.ts +1207 -0
  32. package/std/crypto/rsa.ts +663 -0
  33. package/std/crypto/sha256.ts +2 -3
  34. package/std/crypto/x25519.ts +3 -4
  35. package/std/crypto/x509.ts +1054 -58
  36. package/std/net/dns-config.ts +734 -0
  37. package/std/net/dns-message.ts +517 -0
  38. package/std/net/dns-resolver.ts +1015 -0
  39. package/std/net/dns.ts +478 -0
  40. package/std/net/http-compress.ts +393 -0
  41. package/std/net/http1-client.ts +1227 -0
  42. package/std/net/http1-server.ts +101 -1
  43. package/std/net/http1.ts +9 -9
  44. package/std/net/tls/client.ts +1094 -0
  45. package/std/net/tls/codec.ts +585 -3
  46. package/std/net/tls/record-client.ts +1192 -0
  47. package/std/net/tls/verify.ts +221 -0
  48. package/std/net/tls-tcp.ts +642 -11
  49. package/std/net/tls.ts +2 -2
  50. package/std/net/url.ts +559 -4
  51. package/std/yaml-write.ts +415 -0
package/std/cli.ts CHANGED
@@ -12,13 +12,15 @@
12
12
  * menu.row("--times", "<n>", "say it n times");
13
13
  * console.log(menu.text());
14
14
  *
15
- * **The terminal's own colours.** A `Style` paints with the eight basic SGR
16
- * colours, bold and faint, never a fixed RGB or 256-palette tone. Every theme
17
- * redefines those eight, so the menu comes out in whatever palette the reader
18
- * chose, and a terminal with no theme set paints them in its built-in
19
- * defaults. A terminal with no colours at all (`tput colors` says fewer than
20
- * eight) gets the failsafe: the same structure in bold and underline, which a
21
- * monochrome terminal still shows. Colour that is forced is the theme's.
15
+ * **The terminal's own colours.** A `Style` paints with the sixteen SGR
16
+ * colours (the eight basic ones and their bright twins), their backgrounds
17
+ * and the attributes, never a fixed RGB or 256-palette tone unless the caller
18
+ * asks for one through `sgr`. Every theme redefines those sixteen, so the
19
+ * menu comes out in whatever palette the reader chose, and a terminal with no
20
+ * theme set paints them in its built-in defaults. A terminal with no colours
21
+ * at all (`tput colors` says fewer than eight) gets the failsafe: the same
22
+ * structure in bold and underline, which a monochrome terminal still shows,
23
+ * and no colour from a colour painter. Colour that is forced is the theme's.
22
24
  *
23
25
  * **Colour is for a person reading a terminal**, and nothing else may see it:
24
26
  * a script that captures `--help`, a test that compares it, a pipe into `less`
@@ -56,18 +58,92 @@ const PALETTE_THEME: i32 = 0
56
58
  /** `paletteOf`'s answer: marked up in attributes only, the failsafe. */
57
59
  const PALETTE_MONO: i32 = 2
58
60
 
61
+ /*
62
+ * The SGR parameters `Style`'s painters use, exported so a caller composes a
63
+ * list for `sgr` (`${SGR_BOLD};${SGR_RED}`) or a role (`flagThemed`) without
64
+ * spelling the numbers. The first sixteen are the colours a theme redefines:
65
+ * the eight basic ones and their bright twins.
66
+ */
67
+ export const SGR_BLACK: string = "30"
68
+ export const SGR_RED: string = "31"
69
+ export const SGR_GREEN: string = "32"
70
+ export const SGR_YELLOW: string = "33"
71
+ export const SGR_BLUE: string = "34"
72
+ export const SGR_MAGENTA: string = "35"
73
+ export const SGR_CYAN: string = "36"
74
+ export const SGR_WHITE: string = "37"
75
+ export const SGR_BRIGHT_BLACK: string = "90"
76
+ export const SGR_BRIGHT_RED: string = "91"
77
+ export const SGR_BRIGHT_GREEN: string = "92"
78
+ export const SGR_BRIGHT_YELLOW: string = "93"
79
+ export const SGR_BRIGHT_BLUE: string = "94"
80
+ export const SGR_BRIGHT_MAGENTA: string = "95"
81
+ export const SGR_BRIGHT_CYAN: string = "96"
82
+ export const SGR_BRIGHT_WHITE: string = "97"
83
+ export const SGR_BG_BLACK: string = "40"
84
+ export const SGR_BG_RED: string = "41"
85
+ export const SGR_BG_GREEN: string = "42"
86
+ export const SGR_BG_YELLOW: string = "43"
87
+ export const SGR_BG_BLUE: string = "44"
88
+ export const SGR_BG_MAGENTA: string = "45"
89
+ export const SGR_BG_CYAN: string = "46"
90
+ export const SGR_BG_WHITE: string = "47"
91
+ export const SGR_BG_BRIGHT_BLACK: string = "100"
92
+ export const SGR_BG_BRIGHT_RED: string = "101"
93
+ export const SGR_BG_BRIGHT_GREEN: string = "102"
94
+ export const SGR_BG_BRIGHT_YELLOW: string = "103"
95
+ export const SGR_BG_BRIGHT_BLUE: string = "104"
96
+ export const SGR_BG_BRIGHT_MAGENTA: string = "105"
97
+ export const SGR_BG_BRIGHT_CYAN: string = "106"
98
+ export const SGR_BG_BRIGHT_WHITE: string = "107"
99
+ export const SGR_BOLD: string = "1"
100
+ export const SGR_FAINT: string = "2"
101
+ export const SGR_ITALIC: string = "3"
102
+ export const SGR_UNDERLINE: string = "4"
103
+ export const SGR_INVERSE: string = "7"
104
+ export const SGR_STRIKETHROUGH: string = "9"
105
+
59
106
  /**
60
107
  * How one output stream is painted. `on` says whether to mark the text up at
61
108
  * all, and `colour` whether the terminal has colours to mark it up with;
62
109
  * without them each mark falls back to bold, underline or nothing.
110
+ *
111
+ * Each help role (`heading`, `name`, `flag`, `meta`, `dim`) keeps a pair of
112
+ * SGR lists, the theme's and the failsafe's, so a program recolours its menu
113
+ * by setting a pair (`flagThemed`, `flagMono`) and `styleFor` still decides
114
+ * whether, and which of the two, it paints. An empty list leaves the role
115
+ * plain.
63
116
  */
64
117
  export class Style {
65
118
  on: boolean
66
119
  colour: boolean
120
+ headingThemed: string
121
+ headingMono: string
122
+ nameThemed: string
123
+ nameMono: string
124
+ flagThemed: string
125
+ flagMono: string
126
+ metaThemed: string
127
+ metaMono: string
128
+ dimThemed: string
129
+ dimMono: string
67
130
 
68
131
  constructor(on: boolean, colour: boolean) {
69
132
  this.on = on
70
133
  this.colour = colour
134
+ // Bold magenta, spelled out: a template here would allocate per Style.
135
+ this.headingThemed = "1;35"
136
+ this.headingMono = SGR_BOLD
137
+ this.nameThemed = "1;35"
138
+ this.nameMono = SGR_BOLD
139
+ this.flagThemed = SGR_CYAN
140
+ this.flagMono = SGR_BOLD
141
+ this.metaThemed = SGR_YELLOW
142
+ this.metaMono = SGR_UNDERLINE
143
+ // Faint rather than bright black, which Solarized makes the background;
144
+ // plain without colour, where the bold flags already stand apart from it.
145
+ this.dimThemed = SGR_FAINT
146
+ this.dimMono = ""
71
147
  }
72
148
 
73
149
  /**
@@ -84,33 +160,246 @@ export class Style {
84
160
  return `${CSI}${code}m${text}${CSI}0m`
85
161
  }
86
162
 
87
- /** A section heading: bold, in the theme's magenta. */
163
+ /** A section heading, in `headingThemed` or `headingMono`. */
88
164
  heading(text: string): string {
89
- return this.paint(text, "1;35", "1")
165
+ return this.paint(text, this.headingThemed, this.headingMono)
90
166
  }
91
167
 
92
- /** The tool's own name where it opens a line. */
168
+ /**
169
+ * The tool's own name where it opens a line, in `nameThemed` or
170
+ * `nameMono`.
171
+ */
93
172
  name(text: string): string {
94
- return this.paint(text, "1;35", "1")
173
+ return this.paint(text, this.nameThemed, this.nameMono)
95
174
  }
96
175
 
97
- /** A flag, or a command a person would type. */
176
+ /**
177
+ * A flag, or a command a person would type, in `flagThemed` or
178
+ * `flagMono`.
179
+ */
98
180
  flag(text: string): string {
99
- return this.paint(text, "36", "1")
181
+ return this.paint(text, this.flagThemed, this.flagMono)
100
182
  }
101
183
 
102
- /** A placeholder the person fills in: `<file.ts>`, `speed|size`. */
184
+ /**
185
+ * A placeholder the person fills in, such as `<file.ts>` or `speed|size`, in
186
+ * `metaThemed` or `metaMono`.
187
+ */
103
188
  meta(text: string): string {
104
- return this.paint(text, "33", "4")
189
+ return this.paint(text, this.metaThemed, this.metaMono)
105
190
  }
106
191
 
107
192
  /**
108
- * Text that explains rather than names: descriptions, notes. Faint rather
109
- * than bright black, which Solarized makes the background; plain without
110
- * colour, where the bold flags already stand apart from it.
193
+ * Text that explains rather than names, such as descriptions and notes, in
194
+ * `dimThemed` or `dimMono`.
111
195
  */
112
196
  dim(text: string): string {
113
- return this.paint(text, "2", "")
197
+ return this.paint(text, this.dimThemed, this.dimMono)
198
+ }
199
+
200
+ /**
201
+ * `text` painted with any SGR parameter list (`"1;31"`, `"38;5;208"`,
202
+ * `"38;2;255;128;0"`) when colour is on, and unchanged otherwise: the way to
203
+ * 256-colour and truecolor, which ignore the reader's theme, so they stay
204
+ * the caller's explicit choice. The failsafe paints nothing, since the list
205
+ * may name a colour a monochrome terminal cannot show.
206
+ */
207
+ sgr(text: string, codes: string): string {
208
+ return this.paint(text, codes, "")
209
+ }
210
+
211
+ // The colour painters go through `sgr`, so the failsafe, which has no
212
+ // colours to show, paints none of them; the attribute painters paint under
213
+ // both.
214
+
215
+ /** `text` in the theme's black. */
216
+ black(text: string): string {
217
+ return this.sgr(text, SGR_BLACK)
218
+ }
219
+
220
+ /** `text` in the theme's red. */
221
+ red(text: string): string {
222
+ return this.sgr(text, SGR_RED)
223
+ }
224
+
225
+ /** `text` in the theme's green. */
226
+ green(text: string): string {
227
+ return this.sgr(text, SGR_GREEN)
228
+ }
229
+
230
+ /** `text` in the theme's yellow. */
231
+ yellow(text: string): string {
232
+ return this.sgr(text, SGR_YELLOW)
233
+ }
234
+
235
+ /** `text` in the theme's blue. */
236
+ blue(text: string): string {
237
+ return this.sgr(text, SGR_BLUE)
238
+ }
239
+
240
+ /** `text` in the theme's magenta. */
241
+ magenta(text: string): string {
242
+ return this.sgr(text, SGR_MAGENTA)
243
+ }
244
+
245
+ /** `text` in the theme's cyan. */
246
+ cyan(text: string): string {
247
+ return this.sgr(text, SGR_CYAN)
248
+ }
249
+
250
+ /** `text` in the theme's white. */
251
+ white(text: string): string {
252
+ return this.sgr(text, SGR_WHITE)
253
+ }
254
+
255
+ /** `text` in the theme's bright black (gray). */
256
+ brightBlack(text: string): string {
257
+ return this.sgr(text, SGR_BRIGHT_BLACK)
258
+ }
259
+
260
+ /** `text` in the theme's bright red. */
261
+ brightRed(text: string): string {
262
+ return this.sgr(text, SGR_BRIGHT_RED)
263
+ }
264
+
265
+ /** `text` in the theme's bright green. */
266
+ brightGreen(text: string): string {
267
+ return this.sgr(text, SGR_BRIGHT_GREEN)
268
+ }
269
+
270
+ /** `text` in the theme's bright yellow. */
271
+ brightYellow(text: string): string {
272
+ return this.sgr(text, SGR_BRIGHT_YELLOW)
273
+ }
274
+
275
+ /** `text` in the theme's bright blue. */
276
+ brightBlue(text: string): string {
277
+ return this.sgr(text, SGR_BRIGHT_BLUE)
278
+ }
279
+
280
+ /** `text` in the theme's bright magenta. */
281
+ brightMagenta(text: string): string {
282
+ return this.sgr(text, SGR_BRIGHT_MAGENTA)
283
+ }
284
+
285
+ /** `text` in the theme's bright cyan. */
286
+ brightCyan(text: string): string {
287
+ return this.sgr(text, SGR_BRIGHT_CYAN)
288
+ }
289
+
290
+ /** `text` in the theme's bright white. */
291
+ brightWhite(text: string): string {
292
+ return this.sgr(text, SGR_BRIGHT_WHITE)
293
+ }
294
+
295
+ /** `text` on the theme's black. */
296
+ bgBlack(text: string): string {
297
+ return this.sgr(text, SGR_BG_BLACK)
298
+ }
299
+
300
+ /** `text` on the theme's red. */
301
+ bgRed(text: string): string {
302
+ return this.sgr(text, SGR_BG_RED)
303
+ }
304
+
305
+ /** `text` on the theme's green. */
306
+ bgGreen(text: string): string {
307
+ return this.sgr(text, SGR_BG_GREEN)
308
+ }
309
+
310
+ /** `text` on the theme's yellow. */
311
+ bgYellow(text: string): string {
312
+ return this.sgr(text, SGR_BG_YELLOW)
313
+ }
314
+
315
+ /** `text` on the theme's blue. */
316
+ bgBlue(text: string): string {
317
+ return this.sgr(text, SGR_BG_BLUE)
318
+ }
319
+
320
+ /** `text` on the theme's magenta. */
321
+ bgMagenta(text: string): string {
322
+ return this.sgr(text, SGR_BG_MAGENTA)
323
+ }
324
+
325
+ /** `text` on the theme's cyan. */
326
+ bgCyan(text: string): string {
327
+ return this.sgr(text, SGR_BG_CYAN)
328
+ }
329
+
330
+ /** `text` on the theme's white. */
331
+ bgWhite(text: string): string {
332
+ return this.sgr(text, SGR_BG_WHITE)
333
+ }
334
+
335
+ /** `text` on the theme's bright black. */
336
+ bgBrightBlack(text: string): string {
337
+ return this.sgr(text, SGR_BG_BRIGHT_BLACK)
338
+ }
339
+
340
+ /** `text` on the theme's bright red. */
341
+ bgBrightRed(text: string): string {
342
+ return this.sgr(text, SGR_BG_BRIGHT_RED)
343
+ }
344
+
345
+ /** `text` on the theme's bright green. */
346
+ bgBrightGreen(text: string): string {
347
+ return this.sgr(text, SGR_BG_BRIGHT_GREEN)
348
+ }
349
+
350
+ /** `text` on the theme's bright yellow. */
351
+ bgBrightYellow(text: string): string {
352
+ return this.sgr(text, SGR_BG_BRIGHT_YELLOW)
353
+ }
354
+
355
+ /** `text` on the theme's bright blue. */
356
+ bgBrightBlue(text: string): string {
357
+ return this.sgr(text, SGR_BG_BRIGHT_BLUE)
358
+ }
359
+
360
+ /** `text` on the theme's bright magenta. */
361
+ bgBrightMagenta(text: string): string {
362
+ return this.sgr(text, SGR_BG_BRIGHT_MAGENTA)
363
+ }
364
+
365
+ /** `text` on the theme's bright cyan. */
366
+ bgBrightCyan(text: string): string {
367
+ return this.sgr(text, SGR_BG_BRIGHT_CYAN)
368
+ }
369
+
370
+ /** `text` on the theme's bright white. */
371
+ bgBrightWhite(text: string): string {
372
+ return this.sgr(text, SGR_BG_BRIGHT_WHITE)
373
+ }
374
+
375
+ /** `text` bold. */
376
+ bold(text: string): string {
377
+ return this.paint(text, SGR_BOLD, SGR_BOLD)
378
+ }
379
+
380
+ /** `text` faint. */
381
+ faint(text: string): string {
382
+ return this.paint(text, SGR_FAINT, SGR_FAINT)
383
+ }
384
+
385
+ /** `text` italic, where the terminal has it. */
386
+ italic(text: string): string {
387
+ return this.paint(text, SGR_ITALIC, SGR_ITALIC)
388
+ }
389
+
390
+ /** `text` underlined. */
391
+ underline(text: string): string {
392
+ return this.paint(text, SGR_UNDERLINE, SGR_UNDERLINE)
393
+ }
394
+
395
+ /** `text` with foreground and background swapped. */
396
+ inverse(text: string): string {
397
+ return this.paint(text, SGR_INVERSE, SGR_INVERSE)
398
+ }
399
+
400
+ /** `text` struck through. */
401
+ strikethrough(text: string): string {
402
+ return this.paint(text, SGR_STRIKETHROUGH, SGR_STRIKETHROUGH)
114
403
  }
115
404
  }
116
405
 
@@ -0,0 +1,290 @@
1
+ /**
2
+ * `nish/compress/checksum` — the two checksums the compressed formats carry:
3
+ * CRC-32 (ISO 3309, the polynomial gzip's trailer uses, RFC 1952 §8) and
4
+ * Adler-32 (zlib's trailer, RFC 1950 §9).
5
+ *
6
+ * import { Crc32 } from "nish/compress/checksum";
7
+ *
8
+ * const crc = new Crc32(); // the tables, once
9
+ * let c: u32 = crc.update(toU32(0), body, 0, 100);
10
+ * c = crc.update(c, body, 100, toI32(body.length) - 100); // the same as one call
11
+ *
12
+ * A module has no global state, so CRC-32's tables live in a `Crc32` object:
13
+ * build one and keep it, because building it is 4,096 table entries (about
14
+ * ten microseconds) and an update of a 5 KB body is under one. `crc32`
15
+ * is the one-off convenience that builds a table for one call.
16
+ *
17
+ * CRC-32 is slicing-by-8: eight 256-entry tables, eight bytes per step with
18
+ * one table read per byte and no dependency between the reads of a step
19
+ * (Kounavis and Berry, "A Systematic Approach to Building High Performance
20
+ * Software-based CRC Generators", 2005). From 80 bytes on it is also braided
21
+ * five ways (Kadatch and Jenkins, 2010), so five steps are in flight at once;
22
+ * the braids have a second set of eight tables. Adler-32 defers its two modulo
23
+ * reductions to once every 5,552 bytes, the most that cannot overflow 32 bits
24
+ * (RFC 1950 §9 and zlib's `NMAX`).
25
+ *
26
+ * Neither is a cryptographic hash: both detect accidental corruption only.
27
+ * Written from the specifications, not ported from another implementation.
28
+ *
29
+ * The table reads in `update` are `nish:unsafe`'s `uncheckedGet`: every index
30
+ * is a byte plus a multiple of 256 below 2,048, and both tables are built here
31
+ * at exactly that length and never replaced, which is the whole proof. The input
32
+ * window is checked once, before the loop.
33
+ */
34
+ import { uncheckedGet, uncheckedSet } from "nish:unsafe"
35
+
36
+ /** The reflected CRC-32 polynomial, x^32 + x^26 + ... + 1 (RFC 1952 §8). */
37
+ const CRC32_POLY: i64 = 0xedb88320
38
+
39
+ /** The entries of the eight slicing tables, 256 each. */
40
+ const CRC32_TABLE_SIZE: i32 = 2048
41
+
42
+ /**
43
+ * The braids `Crc32.update` runs at once over a long input, each over every
44
+ * fifth 8-byte word, and the bytes a block of one word per braid spans.
45
+ */
46
+ const CRC32_BRAIDS: i32 = 5
47
+ const CRC32_BLOCK: i32 = 40
48
+
49
+ /** The shortest input `Crc32.update` braids: two blocks, one braided and the last joined. */
50
+ const CRC32_BRAID_MIN: i32 = 80
51
+
52
+ /** zlib's `NMAX`: the most bytes Adler-32's sums take before they must be reduced. */
53
+ const ADLER32_NMAX: i32 = 5552
54
+
55
+ /** The Adler-32 modulus, the largest prime below 2^16 (RFC 1950 §9). */
56
+ const ADLER32_BASE: i32 = 65521
57
+
58
+ /**
59
+ * The little-endian 64-bit word at `buf[p .. p + 8)`, which the caller has
60
+ * checked. `p`'s range makes each `p + k` an `add nsw`, which lets LLVM load
61
+ * the word at once.
62
+ */
63
+ const checksumLoad64 = (buf: u8[], p: integer<0, 2147483639>): u64 =>
64
+ toU64(uncheckedGet(buf, p)) |
65
+ (toU64(uncheckedGet(buf, p + 1)) << toU64(8)) |
66
+ (toU64(uncheckedGet(buf, p + 2)) << toU64(16)) |
67
+ (toU64(uncheckedGet(buf, p + 3)) << toU64(24)) |
68
+ (toU64(uncheckedGet(buf, p + 4)) << toU64(32)) |
69
+ (toU64(uncheckedGet(buf, p + 5)) << toU64(40)) |
70
+ (toU64(uncheckedGet(buf, p + 6)) << toU64(48)) |
71
+ (toU64(uncheckedGet(buf, p + 7)) << toU64(56))
72
+
73
+ /**
74
+ * One slicing-by-8 step: the register `c` advanced over the eight bytes of
75
+ * `w`. `t` is the 2,048-entry table, which every caller has checked.
76
+ */
77
+ const crc32Step = (t: u32[], c: u32, w: u64): u32 => {
78
+ const lo: u32 = c ^ toU32(w)
79
+ const hi: u32 = toU32(w >> toU64(32))
80
+ return (
81
+ uncheckedGet(t, 1792 + toI32(lo & 255)) ^
82
+ uncheckedGet(t, 1536 + toI32((lo >>> 8) & 255)) ^
83
+ uncheckedGet(t, 1280 + toI32((lo >>> 16) & 255)) ^
84
+ uncheckedGet(t, 1024 + toI32(lo >>> 24)) ^
85
+ uncheckedGet(t, 768 + toI32(hi & 255)) ^
86
+ uncheckedGet(t, 512 + toI32((hi >>> 8) & 255)) ^
87
+ uncheckedGet(t, 256 + toI32((hi >>> 16) & 255)) ^
88
+ uncheckedGet(t, toI32(hi >>> 24))
89
+ )
90
+ }
91
+
92
+ /** Panics unless `buf[off .. off + len)` lies inside `buf`. */
93
+ const checksumWindow = (what: string, buf: u8[], off: i32, len: i32): void => {
94
+ if (off < 0 || len < 0 || off > toI32(buf.length) - len) {
95
+ panic(`${what}: the window lies outside its array`)
96
+ }
97
+ }
98
+
99
+ /**
100
+ * CRC-32's lookup tables, built once and read by every `update`. The object
101
+ * holds nothing else, so one may be shared by every compressor and reader in
102
+ * a thread, and by threads that only read it.
103
+ */
104
+ export class Crc32 {
105
+ /** `table[k * 256 + b]`: the CRC of byte `b` followed by `k` zero bytes. */
106
+ readonly table: u32[]
107
+ /**
108
+ * `braid[k * 256 + b]`: the same, followed by the 32 bytes of the other
109
+ * four braids' words as well, which a braid steps over.
110
+ */
111
+ readonly braid: u32[]
112
+
113
+ /** Builds the eight tables and their braided form. */
114
+ constructor() {
115
+ const t: u32[] = new Array<u32>(CRC32_TABLE_SIZE)
116
+ for (let i: i32 = 0; i < 256; i += 1) {
117
+ let c: u32 = toU32(i)
118
+ for (let k: i32 = 0; k < 8; k += 1) {
119
+ c = (c & 1) !== 0 ? toU32(CRC32_POLY) ^ (c >>> 1) : c >>> 1
120
+ }
121
+ uncheckedSet(t, i, c)
122
+ }
123
+ for (let i: i32 = 256; i < CRC32_TABLE_SIZE; i += 1) {
124
+ const prev: u32 = uncheckedGet(t, i - 256)
125
+ uncheckedSet(t, i, (prev >>> 8) ^ uncheckedGet(t, toI32(prev & 255)))
126
+ }
127
+ this.table = t
128
+ // A register is linear in its bytes, so each braided table is its eight
129
+ // one-bit entries, stepped over the 32 bytes, and XORs of them.
130
+ const braid: u32[] = new Array<u32>(CRC32_TABLE_SIZE)
131
+ const bits: u32[] = new Array<u32>(8)
132
+ for (let k: i32 = 0; k < 8; k += 1) {
133
+ for (let i: i32 = 0; i < 8; i += 1) {
134
+ let c: u32 = uncheckedGet(t, k * 256 + (toI32(1) << i))
135
+ for (let z: i32 = 0; z < (CRC32_BRAIDS - 1) * 8; z += 1) {
136
+ c = (c >>> 8) ^ uncheckedGet(t, toI32(c & 255))
137
+ }
138
+ bits[i] = c
139
+ }
140
+ uncheckedSet(braid, k * 256, toU32(0))
141
+ for (let b: i32 = 1; b < 256; b += 1) {
142
+ const low: i32 = 31 - toI32(Math.clz32(toU32(b & -b)))
143
+ if (low >= 0 && low < 8) {
144
+ uncheckedSet(braid, k * 256 + b, uncheckedGet(braid, k * 256 + (b & (b - 1))) ^ bits[low])
145
+ }
146
+ }
147
+ }
148
+ this.braid = braid
149
+ }
150
+
151
+ /**
152
+ * The CRC-32 of the bytes `crc` was the CRC of, followed by
153
+ * `buf[off .. off + len)`. Start a new checksum from 0. A window outside
154
+ * `buf` panics.
155
+ */
156
+ update(crc: u32, buf: u8[], off: i32, len: i32): u32 {
157
+ checksumWindow("Crc32.update", buf, off, len)
158
+ const t: u32[] = this.table
159
+ const bt: u32[] = this.braid
160
+ if (toI32(t.length) !== CRC32_TABLE_SIZE || toI32(bt.length) !== CRC32_TABLE_SIZE) {
161
+ panic("Crc32.update: the table is not its size")
162
+ }
163
+ let c: u32 = ~crc
164
+ let p: i32 = off
165
+ const end: i32 = off + len
166
+ if (len >= CRC32_BRAID_MIN) {
167
+ // Braided (Kadatch and Jenkins, "Everything we know about CRC but
168
+ // afraid to forget", 2010): five chains, each over every fifth 8-byte
169
+ // word, so a step's table reads overlap the other four's instead of
170
+ // waiting on its own last. A braid's table also steps it over the
171
+ // other braids' 32 bytes, so before each block every register sits at
172
+ // its own word's place. The last block is taken one word at a time
173
+ // with the plain table, each braid's register joining as its word
174
+ // comes, which adds them into one.
175
+ const blocks: i32 = len / CRC32_BLOCK
176
+ const lastBlock: i32 = off + (blocks - 1) * CRC32_BLOCK
177
+ let c1: u32 = 0
178
+ let c2: u32 = 0
179
+ let c3: u32 = 0
180
+ let c4: u32 = 0
181
+ // Each word's position is a local the loop condition bounds, which
182
+ // is what lets it enter the loader's range without a check.
183
+ let p1: i32 = p + 8
184
+ let p2: i32 = p + 16
185
+ let p3: i32 = p + 24
186
+ let p4: i32 = p + 32
187
+ while (
188
+ p < lastBlock &&
189
+ p >= 0 &&
190
+ p1 >= 0 &&
191
+ p2 >= 0 &&
192
+ p3 >= 0 &&
193
+ p4 >= 0 &&
194
+ p4 <= 2147483639 &&
195
+ p3 <= 2147483639 &&
196
+ p2 <= 2147483639 &&
197
+ p1 <= 2147483639 &&
198
+ p <= 2147483639
199
+ ) {
200
+ c = crc32Step(bt, c, checksumLoad64(buf, p))
201
+ c1 = crc32Step(bt, c1, checksumLoad64(buf, p1))
202
+ c2 = crc32Step(bt, c2, checksumLoad64(buf, p2))
203
+ c3 = crc32Step(bt, c3, checksumLoad64(buf, p3))
204
+ c4 = crc32Step(bt, c4, checksumLoad64(buf, p4))
205
+ p += CRC32_BLOCK
206
+ p1 += CRC32_BLOCK
207
+ p2 += CRC32_BLOCK
208
+ p3 += CRC32_BLOCK
209
+ p4 += CRC32_BLOCK
210
+ }
211
+ if (
212
+ p >= 0 &&
213
+ p1 >= 0 &&
214
+ p2 >= 0 &&
215
+ p3 >= 0 &&
216
+ p4 >= 0 &&
217
+ p4 <= 2147483639 &&
218
+ p3 <= 2147483639 &&
219
+ p2 <= 2147483639 &&
220
+ p1 <= 2147483639 &&
221
+ p <= 2147483639
222
+ ) {
223
+ c = crc32Step(t, c, checksumLoad64(buf, p))
224
+ c = crc32Step(t, c ^ c1, checksumLoad64(buf, p1))
225
+ c = crc32Step(t, c ^ c2, checksumLoad64(buf, p2))
226
+ c = crc32Step(t, c ^ c3, checksumLoad64(buf, p3))
227
+ c = crc32Step(t, c ^ c4, checksumLoad64(buf, p4))
228
+ p += CRC32_BLOCK
229
+ }
230
+ }
231
+ const whole: i32 = end - (len & 7)
232
+ while (p < whole && p >= 0 && p <= 2147483639) {
233
+ c = crc32Step(t, c, checksumLoad64(buf, p))
234
+ p += 8
235
+ }
236
+ while (p < end) {
237
+ c = uncheckedGet(t, toI32((c ^ toU32(uncheckedGet(buf, p))) & 255)) ^ (c >>> 8)
238
+ p += 1
239
+ }
240
+ return ~c
241
+ }
242
+ }
243
+
244
+ /**
245
+ * The CRC-32 of `buf[off .. off + len)`. It builds a `Crc32` for the one
246
+ * call, which costs about as much as checksumming 5 KB: keep a `Crc32` for
247
+ * anything repeated. A window outside `buf` panics.
248
+ */
249
+ export const crc32 = (buf: u8[], off: i32, len: i32): u32 => new Crc32().update(toU32(0), buf, off, len)
250
+
251
+ /**
252
+ * The Adler-32 of the bytes `adler` was the Adler-32 of, followed by
253
+ * `buf[off .. off + len)` (RFC 1950 §9). Start a new checksum from 1. A
254
+ * window outside `buf` panics.
255
+ */
256
+ export const adler32Update = (adler: u32, buf: u8[], off: i32, len: i32): u32 => {
257
+ checksumWindow("adler32Update", buf, off, len)
258
+ let s1: u32 = adler & 0xffff
259
+ let s2: u32 = adler >>> 16
260
+ let p: i32 = off
261
+ const end: i32 = off + len
262
+ while (p < end) {
263
+ let stop: i32 = p + ADLER32_NMAX
264
+ if (stop > end) {
265
+ stop = end
266
+ }
267
+ while (p + 4 <= stop) {
268
+ s1 += toU32(uncheckedGet(buf, p))
269
+ s2 += s1
270
+ s1 += toU32(uncheckedGet(buf, p + 1))
271
+ s2 += s1
272
+ s1 += toU32(uncheckedGet(buf, p + 2))
273
+ s2 += s1
274
+ s1 += toU32(uncheckedGet(buf, p + 3))
275
+ s2 += s1
276
+ p += 4
277
+ }
278
+ while (p < stop) {
279
+ s1 += toU32(uncheckedGet(buf, p))
280
+ s2 += s1
281
+ p += 1
282
+ }
283
+ s1 = s1 % toU32(ADLER32_BASE)
284
+ s2 = s2 % toU32(ADLER32_BASE)
285
+ }
286
+ return (s2 << 16) | s1
287
+ }
288
+
289
+ /** The Adler-32 of `buf[off .. off + len)`. A window outside `buf` panics. */
290
+ export const adler32 = (buf: u8[], off: i32, len: i32): u32 => adler32Update(toU32(1), buf, off, len)