@amritk/nish-x86_64-linux 0.23.1 → 0.24.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.
- package/bin/nish +0 -0
- package/docs/AI.md +26 -19
- package/package.json +1 -1
- package/runtime/core/arrays.d.ts +0 -2
- package/runtime/core/arrays.mjs +0 -2
- package/runtime/core/numbers.mjs +2 -3
- package/runtime/nish.d.ts +0 -4
- package/runtime/nish.mjs +2 -5
- package/runtime/runtime-net.c +1 -1
- package/runtime/runtime-term.c +2 -2
- package/runtime/runtime.c +1 -1
- package/std/README.md +20 -0
- package/std/compress/checksum.ts +178 -0
- package/std/compress/deflate.ts +2400 -0
- package/std/compress/gzip.ts +747 -0
- package/std/compress/zlib.ts +168 -0
- package/std/crypto/sha256.ts +2 -3
- package/std/crypto/x25519.ts +3 -4
- package/std/net/http-compress.ts +393 -0
- package/std/net/http1-server.ts +95 -0
|
@@ -0,0 +1,2400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nish/compress/deflate` — DEFLATE (RFC 1951), both ways, in pure Nish: a
|
|
3
|
+
* compressor with levels and a decompressor that refuses malformed input with
|
|
4
|
+
* an error code. `nish/compress/gzip` and `nish/compress/zlib` frame it.
|
|
5
|
+
*
|
|
6
|
+
* import { Deflater, Inflater, DEFLATE_FAST, deflateBound } from "nish/compress/deflate";
|
|
7
|
+
*
|
|
8
|
+
* const deflater = new Deflater(DEFLATE_FAST); // tables, once
|
|
9
|
+
* const out: u8[] = new Array<u8>(deflateBound(len));
|
|
10
|
+
* const end: i32 = deflater.compress(src, off, len, out, 0); // -1: no room
|
|
11
|
+
* const inflater = new Inflater();
|
|
12
|
+
* const n: i32 = inflater.decompress(out, 0, end, back, 0, limit); // < 0: an error
|
|
13
|
+
*
|
|
14
|
+
* **Sans-IO and allocation-free once built.** Both objects take caller-owned
|
|
15
|
+
* windows, `src[off .. off + len)` in and `out[at ..)` out, and answer where
|
|
16
|
+
* the output ends. Everything a call needs — the match finder's hash chains,
|
|
17
|
+
* the block's symbols, the Huffman scratch, the decoder's tables — is
|
|
18
|
+
* allocated by the constructor, about 330 KB for a `Deflater` and 4 KB for an
|
|
19
|
+
* `Inflater`, so build one per thread and reuse it: a call allocates nothing.
|
|
20
|
+
* The free functions `deflateCompress` and `deflateDecompress` build one for
|
|
21
|
+
* a single call, for a program that compresses once.
|
|
22
|
+
*
|
|
23
|
+
* **Levels.** `DEFLATE_STORE` (0) writes stored blocks only. 1 to 3 match
|
|
24
|
+
* greedily on a four-byte hash with a short chain (`DEFLATE_FAST` is 1, about
|
|
25
|
+
* libdeflate's level 1); 4 to 9 match lazily on a three-byte hash with longer
|
|
26
|
+
* chains (`DEFLATE_DEFAULT` is 6). Every block is written as whichever of
|
|
27
|
+
* dynamic Huffman, fixed Huffman and stored is smallest, by its exact size in
|
|
28
|
+
* bits, so no level ever expands its input by more than `deflateBound`
|
|
29
|
+
* allows. A block ends after 16,383 symbols.
|
|
30
|
+
*
|
|
31
|
+
* **Decompression is bounded and total.** `Inflater.decompress` writes at most
|
|
32
|
+
* `limit` bytes, and a stream that would write more answers
|
|
33
|
+
* `DEFLATE_ERR_OUTPUT_LIMIT`, so a small input cannot expand without bound.
|
|
34
|
+
* Every malformed stream — a reserved block type, a stored length whose
|
|
35
|
+
* complement is wrong, an over-subscribed or incomplete code, a symbol no code
|
|
36
|
+
* defines, a distance before the start of the output, input that ends inside
|
|
37
|
+
* the stream — answers its own negative `DEFLATE_ERR_*` code; nothing a stream
|
|
38
|
+
* holds can panic. Bytes after the final block are `DEFLATE_ERR_TRAILING`
|
|
39
|
+
* from `decompress`; `inflate`, the resumable step under it and
|
|
40
|
+
* `nish/compress/gzip`'s reader, stops at the final block and says where.
|
|
41
|
+
*
|
|
42
|
+
* **What is unchecked.** The hot loops read and write through `nish:unsafe`'s
|
|
43
|
+
* `uncheckedGet` and `uncheckedSet`. Each such index is one of: a table
|
|
44
|
+
* entry, below a size the constructor allocated and the `readonly` field
|
|
45
|
+
* keeps; a position the caller's window was checked to contain before the
|
|
46
|
+
* loop; or a match candidate, which the loop checks lies in
|
|
47
|
+
* `[histStart, p)` before reading it. A stream's distances and lengths are
|
|
48
|
+
* checked against the output before any copy.
|
|
49
|
+
*
|
|
50
|
+
* Written from RFC 1951; the code-length construction follows Moffat and
|
|
51
|
+
* Katajainen, "In-place calculation of minimum-redundancy codes" (1995), and
|
|
52
|
+
* the length limit is the Kraft-sum repair of the counts per length. Not
|
|
53
|
+
* ported from another implementation.
|
|
54
|
+
*/
|
|
55
|
+
import { uncheckedGet, uncheckedSet } from "nish:unsafe"
|
|
56
|
+
import { copyBytes } from "nish/bytes"
|
|
57
|
+
|
|
58
|
+
/** Level 0: stored blocks only, the input copied with five bytes of framing per 65,535. */
|
|
59
|
+
export const DEFLATE_STORE: i32 = 0
|
|
60
|
+
|
|
61
|
+
/** Level 1: greedy matching on a short hash chain, for speed over ratio. */
|
|
62
|
+
export const DEFLATE_FAST: i32 = 1
|
|
63
|
+
|
|
64
|
+
/** Level 6: lazy matching, zlib's and gzip's default balance. */
|
|
65
|
+
export const DEFLATE_DEFAULT: i32 = 6
|
|
66
|
+
|
|
67
|
+
/** Level 9: lazy matching on the longest chains. */
|
|
68
|
+
export const DEFLATE_BEST: i32 = 9
|
|
69
|
+
|
|
70
|
+
/** `compress` and its framings: `out` has no room for the whole stream. */
|
|
71
|
+
export const DEFLATE_NO_ROOM: i32 = -1
|
|
72
|
+
|
|
73
|
+
/** The input ends inside the stream. */
|
|
74
|
+
export const DEFLATE_ERR_TRUNCATED: i32 = -2
|
|
75
|
+
|
|
76
|
+
/** A block of the reserved type 3 (RFC 1951 §3.2.3). */
|
|
77
|
+
export const DEFLATE_ERR_BLOCK_TYPE: i32 = -3
|
|
78
|
+
|
|
79
|
+
/** A stored block whose `NLEN` is not the complement of its `LEN` (§3.2.4). */
|
|
80
|
+
export const DEFLATE_ERR_STORED_LENGTH: i32 = -4
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* A dynamic block's code is unusable (§3.2.7): an over-subscribed or
|
|
84
|
+
* incomplete set of lengths, a repeat with nothing to repeat or past the end,
|
|
85
|
+
* more than 286 literal/length or 30 distance codes, or no end-of-block code.
|
|
86
|
+
*/
|
|
87
|
+
export const DEFLATE_ERR_HUFFMAN: i32 = -5
|
|
88
|
+
|
|
89
|
+
/** A code the block's tables do not define, or literal/length 286 or 287, or distance 30 or 31. */
|
|
90
|
+
export const DEFLATE_ERR_SYMBOL: i32 = -6
|
|
91
|
+
|
|
92
|
+
/** A distance that reaches back before the start of the output. */
|
|
93
|
+
export const DEFLATE_ERR_DISTANCE: i32 = -7
|
|
94
|
+
|
|
95
|
+
/** The output would pass `limit` bytes, or the end of `out`. */
|
|
96
|
+
export const DEFLATE_ERR_OUTPUT_LIMIT: i32 = -8
|
|
97
|
+
|
|
98
|
+
/** `decompress`: bytes follow the final block. */
|
|
99
|
+
export const DEFLATE_ERR_TRAILING: i32 = -15
|
|
100
|
+
|
|
101
|
+
/** `Inflater.inflate`: the final block has ended; `inPos` is the first byte after it. */
|
|
102
|
+
export const INFLATE_DONE: i32 = 1
|
|
103
|
+
|
|
104
|
+
/** `Inflater.inflate`: every byte given was used and the stream goes on; call again with more. */
|
|
105
|
+
export const INFLATE_NEED_INPUT: i32 = 2
|
|
106
|
+
|
|
107
|
+
/** `Inflater.inflate`: the next symbol does not fit before `outEnd`; make room and call again. */
|
|
108
|
+
export const INFLATE_NEED_OUTPUT: i32 = 3
|
|
109
|
+
|
|
110
|
+
/** The farthest a match reaches back (§3.2.5), and the size of the chain table. */
|
|
111
|
+
const DEFLATE_WINDOW: i32 = 32768
|
|
112
|
+
|
|
113
|
+
/** The longest match (§3.2.5). */
|
|
114
|
+
const DEFLATE_MAX_MATCH: i32 = 258
|
|
115
|
+
|
|
116
|
+
/** The bits of a hash, and the size of the head table. */
|
|
117
|
+
const DEFLATE_HASH_SIZE: i32 = 32768
|
|
118
|
+
|
|
119
|
+
/** The symbols one block holds before it is written. */
|
|
120
|
+
const DEFLATE_BLOCK_TOKENS: i32 = 16384
|
|
121
|
+
|
|
122
|
+
/** A table position this far up is slid back down before the next block. */
|
|
123
|
+
const DEFLATE_REBASE: i32 = 1073741824
|
|
124
|
+
|
|
125
|
+
/** The largest stored block (§3.2.4). */
|
|
126
|
+
const DEFLATE_STORED_MAX: i32 = 65535
|
|
127
|
+
|
|
128
|
+
/** Huffman's multiplier for the hash (Knuth's 2^32 / phi). */
|
|
129
|
+
const DEFLATE_HASH_MUL: i64 = 2654435761
|
|
130
|
+
|
|
131
|
+
/** Decoder table entry kinds, in bits 8 to 10 of an entry. */
|
|
132
|
+
const INF_LITERAL: i32 = 0
|
|
133
|
+
const INF_LENGTH: i32 = 1
|
|
134
|
+
const INF_END: i32 = 2
|
|
135
|
+
const INF_SLOW: i32 = 3
|
|
136
|
+
const INF_INVALID: i32 = 4
|
|
137
|
+
|
|
138
|
+
/** The bits the literal/length and distance tables index directly; a longer code is decoded a bit at a time. */
|
|
139
|
+
const INF_LIT_BITS: i32 = 10
|
|
140
|
+
const INF_DIST_BITS: i32 = 8
|
|
141
|
+
const INF_CL_BITS: i32 = 7
|
|
142
|
+
|
|
143
|
+
/** The decoder's resumable states. */
|
|
144
|
+
const INF_S_BLOCK: i32 = 0
|
|
145
|
+
const INF_S_STORED: i32 = 1
|
|
146
|
+
const INF_S_HUFF: i32 = 2
|
|
147
|
+
const INF_S_DONE: i32 = 3
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* The most bytes `Deflater.compress` writes for `n` bytes of input, at any
|
|
151
|
+
* level: the input stored, five bytes of framing for every 65,535 and for
|
|
152
|
+
* every block, and slack for the last partial byte. `n` is at most
|
|
153
|
+
* 2^31 - 1 less the framing; a negative `n` answers 0.
|
|
154
|
+
*/
|
|
155
|
+
export const deflateBound = (n: i32): i32 => {
|
|
156
|
+
if (n < 0) {
|
|
157
|
+
return 0
|
|
158
|
+
}
|
|
159
|
+
return n + ((n >> 16) + (n >> 14) + 2) * 5 + 8
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The most bytes a compressed body of `n` input bytes takes in any of this
|
|
164
|
+
* directory's formats: `deflateBound(n)` with room for gzip's 18 bytes of
|
|
165
|
+
* header and trailer, which covers zlib's 6.
|
|
166
|
+
*/
|
|
167
|
+
export const compressBound = (n: i32): i32 => deflateBound(n) + 18
|
|
168
|
+
|
|
169
|
+
/** Panics unless `buf[off .. off + len)` lies inside `buf`. */
|
|
170
|
+
const deflateWindow = (what: string, buf: u8[], off: i32, len: i32): void => {
|
|
171
|
+
if (off < 0 || len < 0 || off > toI32(buf.length) - len) {
|
|
172
|
+
panic(`${what}: the window [${off}, ${off} + ${len}) is outside a buffer of ${toI32(buf.length)} bytes`)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Panics unless `out[p .. p + n)` lies inside `out`: the check every store of
|
|
178
|
+
* the bit writer makes before its unchecked stores. A block's exact size was
|
|
179
|
+
* checked against the room before it was written, so this never fires.
|
|
180
|
+
*/
|
|
181
|
+
const deflateRoom = (out: u8[], p: i32, n: i32): void => {
|
|
182
|
+
if (p < 0 || p > toI32(out.length) - n) {
|
|
183
|
+
panic("Deflater: a write past the room its block was sized for")
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* The little-endian 32-bit word at `b[p .. p + 4)`; the caller has checked the
|
|
189
|
+
* range. `p`'s range is what lets `p + 3` be an `add nsw`, which is what lets
|
|
190
|
+
* LLVM fold the four byte loads into one.
|
|
191
|
+
*/
|
|
192
|
+
const deflateLoad32 = (b: u8[], p: integer<0, 2147483639>): u32 =>
|
|
193
|
+
toU32(uncheckedGet(b, p)) |
|
|
194
|
+
(toU32(uncheckedGet(b, p + 1)) << 8) |
|
|
195
|
+
(toU32(uncheckedGet(b, p + 2)) << 16) |
|
|
196
|
+
(toU32(uncheckedGet(b, p + 3)) << 24)
|
|
197
|
+
|
|
198
|
+
/** The little-endian 64-bit word at `b[p .. p + 8)`; the caller has checked the range. */
|
|
199
|
+
const deflateLoad64 = (b: u8[], p: integer<0, 2147483639>): u64 =>
|
|
200
|
+
toU64(deflateLoad32(b, p)) | (toU64(deflateLoad32(b, p + 4)) << toU64(32))
|
|
201
|
+
|
|
202
|
+
/** Stores `w` little-endian into `b[p .. p + 8)`; the caller has checked the range. */
|
|
203
|
+
const deflateStore64 = (b: u8[], p: integer<0, 2147483639>, w: u64): void => {
|
|
204
|
+
uncheckedSet(b, p, toU8(w & toU64(255)))
|
|
205
|
+
uncheckedSet(b, p + 1, toU8((w >> toU64(8)) & toU64(255)))
|
|
206
|
+
uncheckedSet(b, p + 2, toU8((w >> toU64(16)) & toU64(255)))
|
|
207
|
+
uncheckedSet(b, p + 3, toU8((w >> toU64(24)) & toU64(255)))
|
|
208
|
+
uncheckedSet(b, p + 4, toU8((w >> toU64(32)) & toU64(255)))
|
|
209
|
+
uncheckedSet(b, p + 5, toU8((w >> toU64(40)) & toU64(255)))
|
|
210
|
+
uncheckedSet(b, p + 6, toU8((w >> toU64(48)) & toU64(255)))
|
|
211
|
+
uncheckedSet(b, p + 7, toU8(w >> toU64(56)))
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** The number of trailing zero bits of a nonzero `x`. */
|
|
215
|
+
const deflateCtz64 = (x: u64): i32 => {
|
|
216
|
+
const lo: u32 = toU32(x)
|
|
217
|
+
if (lo !== 0) {
|
|
218
|
+
return toI32(31) - Math.clz32(lo & (toU32(0) - lo))
|
|
219
|
+
}
|
|
220
|
+
const hi: u32 = toU32(x >> toU64(32))
|
|
221
|
+
return toI32(63) - Math.clz32(hi & (toU32(0) - hi))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* How many bytes from `a` and from `b` agree, at most `max`; `a < b` and
|
|
226
|
+
* `b + max` lie inside `src`, which the caller has checked.
|
|
227
|
+
*/
|
|
228
|
+
const deflateMatchLength = (src: u8[], a: i32, b: i32, max: i32): i32 => {
|
|
229
|
+
if (a < 0 || b > 2147483639 - max) {
|
|
230
|
+
panic("deflateMatchLength: a match outside its input")
|
|
231
|
+
}
|
|
232
|
+
let k: i32 = 0
|
|
233
|
+
while (k + 8 <= max) {
|
|
234
|
+
const pa: i32 = a + k
|
|
235
|
+
const pb: i32 = b + k
|
|
236
|
+
if (pa >= 0 && pa <= 2147483639 && pb >= 0 && pb <= 2147483639) {
|
|
237
|
+
const x: u64 = deflateLoad64(src, pa) ^ deflateLoad64(src, pb)
|
|
238
|
+
if (x !== toU64(0)) {
|
|
239
|
+
return k + (deflateCtz64(x) >> 3)
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
return k
|
|
243
|
+
}
|
|
244
|
+
k += 8
|
|
245
|
+
}
|
|
246
|
+
while (k < max && uncheckedGet(src, a + k) === uncheckedGet(src, b + k)) {
|
|
247
|
+
k += 1
|
|
248
|
+
}
|
|
249
|
+
return k
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/** `code`'s low `len` bits in the reverse order, as DEFLATE packs a Huffman code (§3.1.1). */
|
|
253
|
+
const deflateReverse = (code: i32, len: i32): i32 => {
|
|
254
|
+
let v: i32 = code
|
|
255
|
+
let r: i32 = 0
|
|
256
|
+
for (let i: i32 = 0; i < len; i += 1) {
|
|
257
|
+
r = (r << 1) | (v & 1)
|
|
258
|
+
v = v >> 1
|
|
259
|
+
}
|
|
260
|
+
return r
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** The base length of each length symbol 257 + s (§3.2.5). */
|
|
264
|
+
const deflateLengthBase = (s: i32): i32 => {
|
|
265
|
+
if (s < 8) {
|
|
266
|
+
return 3 + s
|
|
267
|
+
}
|
|
268
|
+
if (s === 28) {
|
|
269
|
+
return 258
|
|
270
|
+
}
|
|
271
|
+
return ((toI32(4) + (s & 3)) << ((s >> 2) - 1)) + 3
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** The extra bits of each length symbol 257 + s (§3.2.5). */
|
|
275
|
+
const deflateLengthExtra = (s: i32): i32 => (s < 8 || s === 28 ? 0 : (s >> 2) - 1)
|
|
276
|
+
|
|
277
|
+
/** The base distance of each distance symbol (§3.2.5). */
|
|
278
|
+
const deflateDistBase = (d: i32): i32 => {
|
|
279
|
+
if (d < 4) {
|
|
280
|
+
return 1 + d
|
|
281
|
+
}
|
|
282
|
+
const extra: i32 = (d >> 1) - 1
|
|
283
|
+
return ((toI32(2) + (d & 1)) << extra) + 1
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/** The extra bits of each distance symbol (§3.2.5). */
|
|
287
|
+
const deflateDistExtra = (d: i32): i32 => (d < 4 ? 0 : (d >> 1) - 1)
|
|
288
|
+
|
|
289
|
+
/** The order the code-length code's lengths are sent in (§3.2.7). */
|
|
290
|
+
const deflateClOrder = (i: i32): i32 => {
|
|
291
|
+
switch (i) {
|
|
292
|
+
case 0:
|
|
293
|
+
return 16
|
|
294
|
+
case 1:
|
|
295
|
+
return 17
|
|
296
|
+
case 2:
|
|
297
|
+
return 18
|
|
298
|
+
case 3:
|
|
299
|
+
return 0
|
|
300
|
+
case 4:
|
|
301
|
+
return 8
|
|
302
|
+
case 5:
|
|
303
|
+
return 7
|
|
304
|
+
case 6:
|
|
305
|
+
return 9
|
|
306
|
+
case 7:
|
|
307
|
+
return 6
|
|
308
|
+
case 8:
|
|
309
|
+
return 10
|
|
310
|
+
case 9:
|
|
311
|
+
return 5
|
|
312
|
+
case 10:
|
|
313
|
+
return 11
|
|
314
|
+
case 11:
|
|
315
|
+
return 4
|
|
316
|
+
case 12:
|
|
317
|
+
return 12
|
|
318
|
+
case 13:
|
|
319
|
+
return 3
|
|
320
|
+
case 14:
|
|
321
|
+
return 13
|
|
322
|
+
case 15:
|
|
323
|
+
return 2
|
|
324
|
+
case 16:
|
|
325
|
+
return 14
|
|
326
|
+
case 17:
|
|
327
|
+
return 1
|
|
328
|
+
default:
|
|
329
|
+
return 15
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** The fixed literal/length code's length for symbol `s` (§3.2.6). */
|
|
334
|
+
const deflateFixedLitLength = (s: i32): i32 => {
|
|
335
|
+
if (s < 144) {
|
|
336
|
+
return 8
|
|
337
|
+
}
|
|
338
|
+
if (s < 256) {
|
|
339
|
+
return 9
|
|
340
|
+
}
|
|
341
|
+
if (s < 280) {
|
|
342
|
+
return 7
|
|
343
|
+
}
|
|
344
|
+
return 8
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Fills `codes[0 .. n)` with the canonical code (§3.2.2) of the lengths
|
|
349
|
+
* `lens[0 .. n)`, each already bit-reversed for the LSB-first stream. `count`
|
|
350
|
+
* and `next` are scratch of at least 16 entries. A length of 0 gets code 0.
|
|
351
|
+
*/
|
|
352
|
+
const deflateCanonical = (lens: i32[], n: i32, codes: i32[], count: i32[], next: i32[]): void => {
|
|
353
|
+
if (
|
|
354
|
+
n < 0 ||
|
|
355
|
+
n > toI32(lens.length) ||
|
|
356
|
+
n > toI32(codes.length) ||
|
|
357
|
+
toI32(count.length) < 16 ||
|
|
358
|
+
toI32(next.length) < 16
|
|
359
|
+
) {
|
|
360
|
+
panic("deflateCanonical: a table smaller than its symbols")
|
|
361
|
+
}
|
|
362
|
+
for (let i: i32 = 0; i < 16; i += 1) {
|
|
363
|
+
count[i] = 0
|
|
364
|
+
}
|
|
365
|
+
for (let s: i32 = 0; s < n; s += 1) {
|
|
366
|
+
const l: i32 = lens[s]
|
|
367
|
+
if (l >= 0 && l < 16) {
|
|
368
|
+
count[l] += 1
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
count[0] = 0
|
|
372
|
+
let code: i32 = 0
|
|
373
|
+
for (let l: i32 = 1; l < 16; l += 1) {
|
|
374
|
+
code = (code + count[l - 1]) << 1
|
|
375
|
+
next[l] = code
|
|
376
|
+
}
|
|
377
|
+
for (let s: i32 = 0; s < n; s += 1) {
|
|
378
|
+
const l: i32 = lens[s]
|
|
379
|
+
if (l > 0 && l < 16) {
|
|
380
|
+
codes[s] = deflateReverse(next[l], l)
|
|
381
|
+
next[l] += 1
|
|
382
|
+
} else {
|
|
383
|
+
codes[s] = 0
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* The scratch `deflateLengths` sorts and folds in, sized for the 288
|
|
390
|
+
* literal/length symbols, the largest alphabet.
|
|
391
|
+
*/
|
|
392
|
+
export class DeflateHuffmanScratch {
|
|
393
|
+
/** Symbols sorted by frequency, then by symbol. */
|
|
394
|
+
readonly syms: i32[]
|
|
395
|
+
/** Their frequencies, then (in place) the tree, then their lengths. */
|
|
396
|
+
readonly keys: i32[]
|
|
397
|
+
/** The other half of each radix pass. */
|
|
398
|
+
readonly tmpSyms: i32[]
|
|
399
|
+
readonly tmpKeys: i32[]
|
|
400
|
+
/** The radix pass's 256 buckets. */
|
|
401
|
+
readonly buckets: i32[]
|
|
402
|
+
/** How many codes have each length, 0 to 32. */
|
|
403
|
+
readonly perLength: i32[]
|
|
404
|
+
|
|
405
|
+
/** Allocates the scratch. */
|
|
406
|
+
constructor() {
|
|
407
|
+
this.syms = new Array<i32>(288)
|
|
408
|
+
this.keys = new Array<i32>(288)
|
|
409
|
+
this.tmpSyms = new Array<i32>(288)
|
|
410
|
+
this.tmpKeys = new Array<i32>(288)
|
|
411
|
+
this.buckets = new Array<i32>(256)
|
|
412
|
+
this.perLength = new Array<i32>(33)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Sets `lens[0 .. n)` to code lengths of at most `limit` bits for the
|
|
418
|
+
* frequencies `freq[0 .. n)`: a minimum-redundancy code (Moffat and
|
|
419
|
+
* Katajainen's in-place construction over the symbols sorted by frequency),
|
|
420
|
+
* then, if a length passed `limit`, the counts per length repaired until the
|
|
421
|
+
* Kraft sum is exactly 1 again. A symbol of frequency 0 gets length 0. With
|
|
422
|
+
* fewer than two used symbols, symbols are given length 1 until two have
|
|
423
|
+
* one, so the code is always complete. Frequencies are below 2^16.
|
|
424
|
+
*/
|
|
425
|
+
const deflateLengths = (freq: i32[], n: i32, limit: i32, lens: i32[], w: DeflateHuffmanScratch): void => {
|
|
426
|
+
const syms: i32[] = w.syms
|
|
427
|
+
const keys: i32[] = w.keys
|
|
428
|
+
const tsyms: i32[] = w.tmpSyms
|
|
429
|
+
const tkeys: i32[] = w.tmpKeys
|
|
430
|
+
const buckets: i32[] = w.buckets
|
|
431
|
+
const per: i32[] = w.perLength
|
|
432
|
+
if (
|
|
433
|
+
n < 2 ||
|
|
434
|
+
n > 288 ||
|
|
435
|
+
n > toI32(freq.length) ||
|
|
436
|
+
n > toI32(lens.length) ||
|
|
437
|
+
toI32(syms.length) < 288 ||
|
|
438
|
+
toI32(keys.length) < 288 ||
|
|
439
|
+
toI32(tsyms.length) < 288 ||
|
|
440
|
+
toI32(tkeys.length) < 288 ||
|
|
441
|
+
toI32(buckets.length) < 256 ||
|
|
442
|
+
toI32(per.length) < 33 ||
|
|
443
|
+
limit < 1 ||
|
|
444
|
+
limit > 15
|
|
445
|
+
) {
|
|
446
|
+
panic("deflateLengths: an alphabet outside its scratch")
|
|
447
|
+
}
|
|
448
|
+
// The used symbols, by a two-pass radix sort on the 16-bit frequency.
|
|
449
|
+
let used: i32 = 0
|
|
450
|
+
for (let s: i32 = 0; s < n; s += 1) {
|
|
451
|
+
lens[s] = 0
|
|
452
|
+
const f: i32 = freq[s]
|
|
453
|
+
if (f > 0) {
|
|
454
|
+
uncheckedSet(tsyms, used, s)
|
|
455
|
+
uncheckedSet(tkeys, used, f)
|
|
456
|
+
used += 1
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
if (used < 2) {
|
|
460
|
+
// One code or none: every decoder wants a complete code, so give two
|
|
461
|
+
// symbols one bit each.
|
|
462
|
+
let given: i32 = 0
|
|
463
|
+
for (let s: i32 = 0; s < n && given < 2; s += 1) {
|
|
464
|
+
if (freq[s] > 0) {
|
|
465
|
+
lens[s] = 1
|
|
466
|
+
given += 1
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
for (let s: i32 = 0; s < n && given < 2; s += 1) {
|
|
470
|
+
if (lens[s] === 0) {
|
|
471
|
+
lens[s] = 1
|
|
472
|
+
given += 1
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return
|
|
476
|
+
}
|
|
477
|
+
for (let pass: i32 = 0; pass < 2; pass += 1) {
|
|
478
|
+
const shift: i32 = pass * 8
|
|
479
|
+
for (let b: i32 = 0; b < 256; b += 1) {
|
|
480
|
+
uncheckedSet(buckets, b, 0)
|
|
481
|
+
}
|
|
482
|
+
const fromSyms: i32[] = pass === 0 ? tsyms : syms
|
|
483
|
+
const fromKeys: i32[] = pass === 0 ? tkeys : keys
|
|
484
|
+
const toSyms: i32[] = pass === 0 ? syms : tsyms
|
|
485
|
+
const toKeys: i32[] = pass === 0 ? keys : tkeys
|
|
486
|
+
for (let i: i32 = 0; i < used; i += 1) {
|
|
487
|
+
const b: i32 = (uncheckedGet(fromKeys, i) >> shift) & 255
|
|
488
|
+
uncheckedSet(buckets, b, uncheckedGet(buckets, b) + 1)
|
|
489
|
+
}
|
|
490
|
+
let sum: i32 = 0
|
|
491
|
+
for (let b: i32 = 0; b < 256; b += 1) {
|
|
492
|
+
const c: i32 = uncheckedGet(buckets, b)
|
|
493
|
+
uncheckedSet(buckets, b, sum)
|
|
494
|
+
sum += c
|
|
495
|
+
}
|
|
496
|
+
for (let i: i32 = 0; i < used; i += 1) {
|
|
497
|
+
const k: i32 = uncheckedGet(fromKeys, i)
|
|
498
|
+
const b: i32 = (k >> shift) & 255
|
|
499
|
+
const at: i32 = uncheckedGet(buckets, b)
|
|
500
|
+
uncheckedSet(buckets, b, at + 1)
|
|
501
|
+
uncheckedSet(toSyms, at, uncheckedGet(fromSyms, i))
|
|
502
|
+
uncheckedSet(toKeys, at, k)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
// Two passes leave the sorted run back in `tsyms` / `tkeys`.
|
|
506
|
+
for (let i: i32 = 0; i < used; i += 1) {
|
|
507
|
+
uncheckedSet(syms, i, uncheckedGet(tsyms, i))
|
|
508
|
+
uncheckedSet(keys, i, uncheckedGet(tkeys, i))
|
|
509
|
+
}
|
|
510
|
+
// Moffat and Katajainen, phase 1: each internal node's weight, and each
|
|
511
|
+
// node's parent, in place over the ascending weights.
|
|
512
|
+
uncheckedSet(keys, 0, uncheckedGet(keys, 0) + uncheckedGet(keys, 1))
|
|
513
|
+
let root: i32 = 0
|
|
514
|
+
let leaf: i32 = 2
|
|
515
|
+
for (let next: i32 = 1; next < used - 1; next += 1) {
|
|
516
|
+
if (leaf >= used || uncheckedGet(keys, root) < uncheckedGet(keys, leaf)) {
|
|
517
|
+
uncheckedSet(keys, next, uncheckedGet(keys, root))
|
|
518
|
+
uncheckedSet(keys, root, next)
|
|
519
|
+
root += 1
|
|
520
|
+
} else {
|
|
521
|
+
uncheckedSet(keys, next, uncheckedGet(keys, leaf))
|
|
522
|
+
leaf += 1
|
|
523
|
+
}
|
|
524
|
+
if (leaf >= used || (root < next && uncheckedGet(keys, root) < uncheckedGet(keys, leaf))) {
|
|
525
|
+
uncheckedSet(keys, next, uncheckedGet(keys, next) + uncheckedGet(keys, root))
|
|
526
|
+
uncheckedSet(keys, root, next)
|
|
527
|
+
root += 1
|
|
528
|
+
} else {
|
|
529
|
+
uncheckedSet(keys, next, uncheckedGet(keys, next) + uncheckedGet(keys, leaf))
|
|
530
|
+
leaf += 1
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Phase 2: each internal node's depth.
|
|
534
|
+
uncheckedSet(keys, used - 2, 0)
|
|
535
|
+
for (let next: i32 = used - 3; next >= 0; next -= 1) {
|
|
536
|
+
uncheckedSet(keys, next, uncheckedGet(keys, uncheckedGet(keys, next)) + 1)
|
|
537
|
+
}
|
|
538
|
+
// Phase 3: how many leaves sit at each depth.
|
|
539
|
+
for (let l: i32 = 0; l < 33; l += 1) {
|
|
540
|
+
per[l] = 0
|
|
541
|
+
}
|
|
542
|
+
let avail: i32 = 1
|
|
543
|
+
let usedHere: i32 = 0
|
|
544
|
+
let depth: i32 = 0
|
|
545
|
+
root = used - 2
|
|
546
|
+
let next: i32 = used - 1
|
|
547
|
+
while (avail > 0) {
|
|
548
|
+
while (root >= 0 && uncheckedGet(keys, root) === depth) {
|
|
549
|
+
usedHere += 1
|
|
550
|
+
root -= 1
|
|
551
|
+
}
|
|
552
|
+
while (avail > usedHere) {
|
|
553
|
+
if (depth < 33) {
|
|
554
|
+
per[depth] += 1
|
|
555
|
+
}
|
|
556
|
+
next -= 1
|
|
557
|
+
avail -= 1
|
|
558
|
+
}
|
|
559
|
+
avail = 2 * usedHere
|
|
560
|
+
depth += 1
|
|
561
|
+
usedHere = 0
|
|
562
|
+
}
|
|
563
|
+
// The length limit: fold the deeper codes into `limit`, then lengthen
|
|
564
|
+
// shorter codes until the Kraft sum is exactly 2^limit again.
|
|
565
|
+
if (per[limit + 1] > 0 || depth > limit + 1) {
|
|
566
|
+
for (let l: i32 = limit + 1; l < 33; l += 1) {
|
|
567
|
+
per[limit] += per[l]
|
|
568
|
+
per[l] = 0
|
|
569
|
+
}
|
|
570
|
+
let total: i32 = 0
|
|
571
|
+
for (let l: i32 = limit; l > 0; l -= 1) {
|
|
572
|
+
total += per[l] << (limit - l)
|
|
573
|
+
}
|
|
574
|
+
while (total !== 1 << limit) {
|
|
575
|
+
per[limit] -= 1
|
|
576
|
+
for (let l: i32 = limit - 1; l > 0; l -= 1) {
|
|
577
|
+
if (per[l] !== 0) {
|
|
578
|
+
per[l] -= 1
|
|
579
|
+
per[l + 1] += 2
|
|
580
|
+
break
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
total -= 1
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
// The most frequent symbols take the shortest lengths.
|
|
587
|
+
let j: i32 = used
|
|
588
|
+
for (let l: i32 = 1; l <= limit; l += 1) {
|
|
589
|
+
for (let c: i32 = per[l]; c > 0; c -= 1) {
|
|
590
|
+
j -= 1
|
|
591
|
+
if (j >= 0) {
|
|
592
|
+
const s: i32 = uncheckedGet(syms, j)
|
|
593
|
+
if (s >= 0 && s < n) {
|
|
594
|
+
lens[s] = l
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* A DEFLATE compressor at one level: the match finder's tables, one block of
|
|
603
|
+
* symbols, the Huffman scratch and the bit writer, allocated once. Not shared
|
|
604
|
+
* between threads; reuse it for every call on one.
|
|
605
|
+
*/
|
|
606
|
+
export class Deflater {
|
|
607
|
+
/** `head[h]`: the most recent position whose hash is `h`, plus `delta`; 0 for none. */
|
|
608
|
+
readonly head: i32[]
|
|
609
|
+
/** `prev[p & 32767]`: the position before `p` with `p`'s hash. */
|
|
610
|
+
readonly prev: i32[]
|
|
611
|
+
/** The block's symbols: a literal byte, or `dist << 9 | (256 + len - 3)`. */
|
|
612
|
+
readonly tokens: i32[]
|
|
613
|
+
/** The block's literal/length and distance frequencies. */
|
|
614
|
+
readonly litFreq: i32[]
|
|
615
|
+
readonly distFreq: i32[]
|
|
616
|
+
/** The dynamic code for the block. */
|
|
617
|
+
readonly litLens: i32[]
|
|
618
|
+
readonly litCodes: i32[]
|
|
619
|
+
readonly distLens: i32[]
|
|
620
|
+
readonly distCodes: i32[]
|
|
621
|
+
/** The code-length code, and the run-length coded lengths it codes. */
|
|
622
|
+
readonly clFreq: i32[]
|
|
623
|
+
readonly clLens: i32[]
|
|
624
|
+
readonly clCodes: i32[]
|
|
625
|
+
readonly rle: i32[]
|
|
626
|
+
/** The fixed code (§3.2.6). */
|
|
627
|
+
readonly fixedLitLens: i32[]
|
|
628
|
+
readonly fixedLitCodes: i32[]
|
|
629
|
+
readonly fixedDistLens: i32[]
|
|
630
|
+
readonly fixedDistCodes: i32[]
|
|
631
|
+
/** Length - 3 to length symbol - 257; distance to distance symbol, as `deflateDistSymbol` reads it. */
|
|
632
|
+
readonly lengthSymbol: i32[]
|
|
633
|
+
readonly distSymbol: i32[]
|
|
634
|
+
/** Base and extra bits of each length and distance symbol. */
|
|
635
|
+
readonly lengthBase: i32[]
|
|
636
|
+
readonly lengthExtra: i32[]
|
|
637
|
+
readonly distBase: i32[]
|
|
638
|
+
readonly distExtra: i32[]
|
|
639
|
+
/** Canonical-code and length-building scratch. */
|
|
640
|
+
readonly countScratch: i32[]
|
|
641
|
+
readonly nextScratch: i32[]
|
|
642
|
+
readonly scratch: DeflateHuffmanScratch
|
|
643
|
+
/** Bits written but not yet stored, low bit first, and how many. */
|
|
644
|
+
bitBuf: u64
|
|
645
|
+
bitCount: i32
|
|
646
|
+
/** The level, 0 to 9. */
|
|
647
|
+
readonly level: i32
|
|
648
|
+
/** Candidates tried per position. */
|
|
649
|
+
readonly maxChain: i32
|
|
650
|
+
/** A match this long is taken without looking further. */
|
|
651
|
+
readonly niceLength: i32
|
|
652
|
+
/** A match shorter than this is checked against the next position's (levels 4 to 9); 0 for greedy. */
|
|
653
|
+
readonly lazyLength: i32
|
|
654
|
+
/** The shortest match taken: 4 at levels 1 to 3, whose hash covers four bytes, else 3. */
|
|
655
|
+
readonly minMatch: i32
|
|
656
|
+
/** A table position is an index of the current input plus this. */
|
|
657
|
+
delta: i32
|
|
658
|
+
/** The next call's `delta` floor: past every position the tables hold, by a whole window. */
|
|
659
|
+
base: i32
|
|
660
|
+
/** How many of `tokens` the block holds. */
|
|
661
|
+
count: i32
|
|
662
|
+
/** How many entries of `rle` the block uses. */
|
|
663
|
+
rleCount: i32
|
|
664
|
+
|
|
665
|
+
/** A compressor at `level`, 0 to 9; another level panics. */
|
|
666
|
+
constructor(level: i32) {
|
|
667
|
+
if (level < 0 || level > 9) {
|
|
668
|
+
panic(`Deflater: level ${level} is outside 0 to 9`)
|
|
669
|
+
}
|
|
670
|
+
this.level = level
|
|
671
|
+
let chain: i32 = 0
|
|
672
|
+
let nice: i32 = 0
|
|
673
|
+
let lazy: i32 = 0
|
|
674
|
+
switch (level) {
|
|
675
|
+
case 1:
|
|
676
|
+
chain = 2
|
|
677
|
+
nice = 32
|
|
678
|
+
break
|
|
679
|
+
case 2:
|
|
680
|
+
chain = 6
|
|
681
|
+
nice = 64
|
|
682
|
+
break
|
|
683
|
+
case 3:
|
|
684
|
+
chain = 12
|
|
685
|
+
nice = 128
|
|
686
|
+
break
|
|
687
|
+
case 4:
|
|
688
|
+
chain = 12
|
|
689
|
+
nice = 64
|
|
690
|
+
lazy = 8
|
|
691
|
+
break
|
|
692
|
+
case 5:
|
|
693
|
+
chain = 24
|
|
694
|
+
nice = 128
|
|
695
|
+
lazy = 16
|
|
696
|
+
break
|
|
697
|
+
case 6:
|
|
698
|
+
chain = 48
|
|
699
|
+
nice = 128
|
|
700
|
+
lazy = 16
|
|
701
|
+
break
|
|
702
|
+
case 7:
|
|
703
|
+
chain = 96
|
|
704
|
+
nice = 258
|
|
705
|
+
lazy = 32
|
|
706
|
+
break
|
|
707
|
+
case 8:
|
|
708
|
+
chain = 256
|
|
709
|
+
nice = 258
|
|
710
|
+
lazy = 128
|
|
711
|
+
break
|
|
712
|
+
case 9:
|
|
713
|
+
chain = 1024
|
|
714
|
+
nice = 258
|
|
715
|
+
lazy = 258
|
|
716
|
+
break
|
|
717
|
+
default:
|
|
718
|
+
break
|
|
719
|
+
}
|
|
720
|
+
this.maxChain = chain
|
|
721
|
+
this.niceLength = nice
|
|
722
|
+
this.lazyLength = lazy
|
|
723
|
+
this.minMatch = level >= 4 ? 3 : 4
|
|
724
|
+
this.head = new Array<i32>(DEFLATE_HASH_SIZE)
|
|
725
|
+
this.prev = new Array<i32>(DEFLATE_WINDOW)
|
|
726
|
+
this.delta = 0
|
|
727
|
+
this.base = DEFLATE_WINDOW + 1
|
|
728
|
+
this.tokens = new Array<i32>(DEFLATE_BLOCK_TOKENS)
|
|
729
|
+
this.count = 0
|
|
730
|
+
this.litFreq = new Array<i32>(288)
|
|
731
|
+
this.distFreq = new Array<i32>(32)
|
|
732
|
+
this.litLens = new Array<i32>(288)
|
|
733
|
+
this.litCodes = new Array<i32>(288)
|
|
734
|
+
this.distLens = new Array<i32>(32)
|
|
735
|
+
this.distCodes = new Array<i32>(32)
|
|
736
|
+
this.clFreq = new Array<i32>(19)
|
|
737
|
+
this.clLens = new Array<i32>(19)
|
|
738
|
+
this.clCodes = new Array<i32>(19)
|
|
739
|
+
this.rle = new Array<i32>(320)
|
|
740
|
+
this.rleCount = 0
|
|
741
|
+
this.fixedLitLens = new Array<i32>(288)
|
|
742
|
+
this.fixedLitCodes = new Array<i32>(288)
|
|
743
|
+
this.fixedDistLens = new Array<i32>(32)
|
|
744
|
+
this.fixedDistCodes = new Array<i32>(32)
|
|
745
|
+
this.lengthSymbol = new Array<i32>(256)
|
|
746
|
+
this.distSymbol = new Array<i32>(512)
|
|
747
|
+
this.lengthBase = new Array<i32>(29)
|
|
748
|
+
this.lengthExtra = new Array<i32>(29)
|
|
749
|
+
this.distBase = new Array<i32>(30)
|
|
750
|
+
this.distExtra = new Array<i32>(30)
|
|
751
|
+
this.countScratch = new Array<i32>(16)
|
|
752
|
+
this.nextScratch = new Array<i32>(16)
|
|
753
|
+
this.scratch = new DeflateHuffmanScratch()
|
|
754
|
+
this.bitBuf = 0
|
|
755
|
+
this.bitCount = 0
|
|
756
|
+
for (let s: i32 = 0; s < 29; s += 1) {
|
|
757
|
+
this.lengthBase[s] = deflateLengthBase(s)
|
|
758
|
+
this.lengthExtra[s] = deflateLengthExtra(s)
|
|
759
|
+
}
|
|
760
|
+
for (let s: i32 = 0; s < 29; s += 1) {
|
|
761
|
+
const lo: i32 = this.lengthBase[s] - 3
|
|
762
|
+
// Symbol 27 stops short of 258, which has symbol 28 to itself.
|
|
763
|
+
let hi: i32 = 256
|
|
764
|
+
if (s < 27) {
|
|
765
|
+
hi = this.lengthBase[s + 1] - 3
|
|
766
|
+
} else if (s === 27) {
|
|
767
|
+
hi = 255
|
|
768
|
+
}
|
|
769
|
+
for (let l: i32 = lo; l < hi && l >= 0 && l < 256; l += 1) {
|
|
770
|
+
this.lengthSymbol[l] = s
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
for (let d: i32 = 0; d < 30; d += 1) {
|
|
774
|
+
this.distBase[d] = deflateDistBase(d)
|
|
775
|
+
this.distExtra[d] = deflateDistExtra(d)
|
|
776
|
+
}
|
|
777
|
+
// Distances 1 to 256 directly; above, by (distance - 1) >> 7 from 256 on.
|
|
778
|
+
for (let d: i32 = 0; d < 30; d += 1) {
|
|
779
|
+
const lo: i32 = this.distBase[d]
|
|
780
|
+
const hi: i32 = d === 29 ? 32769 : this.distBase[d + 1]
|
|
781
|
+
for (let dist: i32 = lo; dist < hi; dist += 1) {
|
|
782
|
+
if (dist <= 256) {
|
|
783
|
+
this.distSymbol[dist - 1] = d
|
|
784
|
+
} else {
|
|
785
|
+
const at: i32 = ((dist - 1) >> 7) + 256
|
|
786
|
+
if (at < 512) {
|
|
787
|
+
this.distSymbol[at] = d
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
for (let s: i32 = 0; s < 288; s += 1) {
|
|
793
|
+
this.fixedLitLens[s] = deflateFixedLitLength(s)
|
|
794
|
+
}
|
|
795
|
+
for (let d: i32 = 0; d < 32; d += 1) {
|
|
796
|
+
this.fixedDistLens[d] = 5
|
|
797
|
+
}
|
|
798
|
+
deflateCanonical(this.fixedLitLens, 288, this.fixedLitCodes, this.countScratch, this.nextScratch)
|
|
799
|
+
deflateCanonical(this.fixedDistLens, 32, this.fixedDistCodes, this.countScratch, this.nextScratch)
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Forgets the history: the next call starts a stream from nothing. Only a
|
|
804
|
+
* streaming writer needs it; `compress` starts a new stream on every call.
|
|
805
|
+
*/
|
|
806
|
+
reset(): void {
|
|
807
|
+
this.bitBuf = 0
|
|
808
|
+
this.bitCount = 0
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Compresses `src[off .. off + len)` into `out` from `at` as one raw
|
|
813
|
+
* DEFLATE stream, and answers where it ends, or `DEFLATE_NO_ROOM` when
|
|
814
|
+
* `out` cannot hold it: `deflateBound(len)` bytes always can. A window
|
|
815
|
+
* outside its array panics. Allocates nothing.
|
|
816
|
+
*/
|
|
817
|
+
compress(src: u8[], off: i32, len: i32, out: u8[], at: i32): i32 {
|
|
818
|
+
deflateWindow("Deflater.compress", src, off, len)
|
|
819
|
+
deflateWindow("Deflater.compress", out, at, 0)
|
|
820
|
+
this.bitBuf = 0
|
|
821
|
+
this.bitCount = 0
|
|
822
|
+
this.begin(off)
|
|
823
|
+
const end: i32 = this.compressRange(src, off, off + len, off, true, out, at, toI32(out.length))
|
|
824
|
+
this.finish(off + len)
|
|
825
|
+
if (end < 0) {
|
|
826
|
+
return DEFLATE_NO_ROOM
|
|
827
|
+
}
|
|
828
|
+
return this.flushBits(out, end, toI32(out.length))
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Starts a stream whose history begins at index `start` of the next input:
|
|
833
|
+
* every position the tables hold is pushed a window behind it.
|
|
834
|
+
*/
|
|
835
|
+
begin(start: i32): void {
|
|
836
|
+
if (this.base > DEFLATE_REBASE) {
|
|
837
|
+
this.head.fill(0)
|
|
838
|
+
this.prev.fill(0)
|
|
839
|
+
this.base = DEFLATE_WINDOW + 1
|
|
840
|
+
}
|
|
841
|
+
this.delta = this.base - start
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Ends a stream whose input ended at index `end`: the next stream's
|
|
846
|
+
* positions start a window past every position the tables now hold.
|
|
847
|
+
*/
|
|
848
|
+
finish(end: i32): void {
|
|
849
|
+
this.base = end + this.delta + DEFLATE_WINDOW + 1
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Moves the tables' positions down by `shift`, as the input they index
|
|
854
|
+
* moves down by `shift` bytes; a position that falls below 0 is dropped.
|
|
855
|
+
* The streaming writer calls it when it slides its window.
|
|
856
|
+
*/
|
|
857
|
+
slide(shift: i32): void {
|
|
858
|
+
this.delta = this.delta + shift
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* Writes the whole bytes of the bit buffer, and the last partial byte
|
|
863
|
+
* padded with zeros, into `out` at `op`; answers the end, or
|
|
864
|
+
* `DEFLATE_NO_ROOM`.
|
|
865
|
+
*/
|
|
866
|
+
flushBits(out: u8[], op: i32, oe: i32): i32 {
|
|
867
|
+
const bytes: i32 = (this.bitCount + 7) >> 3
|
|
868
|
+
if (op < 0 || oe > toI32(out.length) || bytes > oe - op) {
|
|
869
|
+
return DEFLATE_NO_ROOM
|
|
870
|
+
}
|
|
871
|
+
let p: i32 = op
|
|
872
|
+
let bb: u64 = this.bitBuf
|
|
873
|
+
for (let i: i32 = 0; i < bytes; i += 1) {
|
|
874
|
+
uncheckedSet(out, p, toU8(bb & toU64(255)))
|
|
875
|
+
bb = bb >> toU64(8)
|
|
876
|
+
p += 1
|
|
877
|
+
}
|
|
878
|
+
this.bitBuf = 0
|
|
879
|
+
this.bitCount = 0
|
|
880
|
+
return p
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* Appends the low `n` bits of `v` (`n` at most 32) to the bit buffer,
|
|
885
|
+
* storing whole words into `out` at `op`; answers the new `op`. The caller
|
|
886
|
+
* has checked the room.
|
|
887
|
+
*/
|
|
888
|
+
putBits(out: u8[], op: i32, v: i32, n: i32): i32 {
|
|
889
|
+
let bb: u64 = this.bitBuf | (toU64(toU32(v)) << toU64(this.bitCount))
|
|
890
|
+
let bc: i32 = this.bitCount + n
|
|
891
|
+
let p: i32 = op
|
|
892
|
+
if (bc >= 32) {
|
|
893
|
+
deflateRoom(out, p, 4)
|
|
894
|
+
uncheckedSet(out, p, toU8(bb & toU64(255)))
|
|
895
|
+
uncheckedSet(out, p + 1, toU8((bb >> toU64(8)) & toU64(255)))
|
|
896
|
+
uncheckedSet(out, p + 2, toU8((bb >> toU64(16)) & toU64(255)))
|
|
897
|
+
uncheckedSet(out, p + 3, toU8((bb >> toU64(24)) & toU64(255)))
|
|
898
|
+
bb = bb >> toU64(32)
|
|
899
|
+
bc -= 32
|
|
900
|
+
p += 4
|
|
901
|
+
}
|
|
902
|
+
this.bitBuf = bb
|
|
903
|
+
this.bitCount = bc
|
|
904
|
+
return p
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
/**
|
|
908
|
+
* Stores whole bytes of the bit buffer into `out` at `op` and drops the
|
|
909
|
+
* partial byte's padding: the byte alignment a stored block's `LEN`
|
|
910
|
+
* starts at. Answers the new `op`; the caller has checked the room.
|
|
911
|
+
*/
|
|
912
|
+
alignBits(out: u8[], op: i32): i32 {
|
|
913
|
+
let p: i32 = op
|
|
914
|
+
let bb: u64 = this.bitBuf
|
|
915
|
+
let bc: i32 = this.bitCount
|
|
916
|
+
deflateRoom(out, p, (bc + 7) >> 3)
|
|
917
|
+
while (bc > 0) {
|
|
918
|
+
uncheckedSet(out, p, toU8(bb & toU64(255)))
|
|
919
|
+
bb = bb >> toU64(8)
|
|
920
|
+
bc -= 8
|
|
921
|
+
p += 1
|
|
922
|
+
}
|
|
923
|
+
this.bitBuf = 0
|
|
924
|
+
this.bitCount = 0
|
|
925
|
+
return p
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* Compresses `src[start .. end)` as blocks into `out[op .. oe)`, matching
|
|
930
|
+
* back as far as `histStart`; `final` marks the last block BFINAL. Answers
|
|
931
|
+
* the new output position, with up to 31 bits still in the bit buffer, or
|
|
932
|
+
* -1 when a block does not fit.
|
|
933
|
+
*/
|
|
934
|
+
compressRange(
|
|
935
|
+
src: u8[],
|
|
936
|
+
start: i32,
|
|
937
|
+
end: i32,
|
|
938
|
+
histStart: i32,
|
|
939
|
+
final: boolean,
|
|
940
|
+
out: u8[],
|
|
941
|
+
op: i32,
|
|
942
|
+
oe: i32
|
|
943
|
+
): i32 {
|
|
944
|
+
if (start < 0 || histStart < 0 || histStart > start || start > end || end > toI32(src.length)) {
|
|
945
|
+
panic("Deflater.compressRange: a range outside its input")
|
|
946
|
+
}
|
|
947
|
+
if (op < 0 || oe > toI32(out.length) || op > oe) {
|
|
948
|
+
panic("Deflater.compressRange: a range outside its output")
|
|
949
|
+
}
|
|
950
|
+
let p: i32 = start
|
|
951
|
+
let o: i32 = op
|
|
952
|
+
if (start === end) {
|
|
953
|
+
if (!final) {
|
|
954
|
+
return o
|
|
955
|
+
}
|
|
956
|
+
// An empty final block, in the fixed code: ten bits.
|
|
957
|
+
if ((this.bitCount + 10 + 7) >> 3 > oe - o) {
|
|
958
|
+
return -1
|
|
959
|
+
}
|
|
960
|
+
o = this.putBits(out, o, toI32(3), toI32(3))
|
|
961
|
+
return this.putBits(out, o, this.fixedLitCodes[256], this.fixedLitLens[256])
|
|
962
|
+
}
|
|
963
|
+
if (this.level === 0) {
|
|
964
|
+
return this.writeStored(src, start, end, final, out, o, oe)
|
|
965
|
+
}
|
|
966
|
+
while (p < end) {
|
|
967
|
+
if (p + this.delta > DEFLATE_REBASE) {
|
|
968
|
+
this.rebase(p)
|
|
969
|
+
}
|
|
970
|
+
const q: i32 =
|
|
971
|
+
this.level >= 4
|
|
972
|
+
? this.collectLazy(src, p, end, histStart)
|
|
973
|
+
: this.collectGreedy(src, p, end, histStart)
|
|
974
|
+
o = this.writeBlock(src, p, q, final && q === end, out, o, oe)
|
|
975
|
+
if (o < 0) {
|
|
976
|
+
return -1
|
|
977
|
+
}
|
|
978
|
+
p = q
|
|
979
|
+
}
|
|
980
|
+
return o
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/**
|
|
984
|
+
* Slides every table position down so that index `p` of the input is a
|
|
985
|
+
* window above the floor again; a position more than a window behind `p`
|
|
986
|
+
* becomes 0, which is never a candidate.
|
|
987
|
+
*/
|
|
988
|
+
rebase(p: i32): void {
|
|
989
|
+
const shift: i32 = p + this.delta - (DEFLATE_WINDOW + 1)
|
|
990
|
+
const head: i32[] = this.head
|
|
991
|
+
const prev: i32[] = this.prev
|
|
992
|
+
for (let i: i32 = 0; i < toI32(head.length); i += 1) {
|
|
993
|
+
const v: i32 = head[i] - shift
|
|
994
|
+
head[i] = v > 0 ? v : 0
|
|
995
|
+
}
|
|
996
|
+
for (let i: i32 = 0; i < toI32(prev.length); i += 1) {
|
|
997
|
+
const v: i32 = prev[i] - shift
|
|
998
|
+
prev[i] = v > 0 ? v : 0
|
|
999
|
+
}
|
|
1000
|
+
this.delta = this.delta - shift
|
|
1001
|
+
this.base = this.base - shift
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* The best match at `p`, after recording `p` in the chains: answers
|
|
1006
|
+
* `len << 16 | dist`, or 0 for none at least `minMatch` long. `p + 4 <=
|
|
1007
|
+
* end`, which the caller checks.
|
|
1008
|
+
*/
|
|
1009
|
+
longest(src: u8[], p: i32, end: i32, histStart: i32): i32 {
|
|
1010
|
+
const head: i32[] = this.head
|
|
1011
|
+
const prev: i32[] = this.prev
|
|
1012
|
+
if (toI32(head.length) !== DEFLATE_HASH_SIZE || toI32(prev.length) !== DEFLATE_WINDOW) {
|
|
1013
|
+
panic("Deflater.longest: a table is not its size")
|
|
1014
|
+
}
|
|
1015
|
+
const word: u32 = deflateLoad32(src, p)
|
|
1016
|
+
const h: i32 =
|
|
1017
|
+
this.minMatch === 3
|
|
1018
|
+
? toI32(((word << 8) * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1019
|
+
: toI32((word * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1020
|
+
const v: i32 = p + this.delta
|
|
1021
|
+
let cand: i32 = uncheckedGet(head, h)
|
|
1022
|
+
uncheckedSet(head, h, v)
|
|
1023
|
+
uncheckedSet(prev, v & (DEFLATE_WINDOW - 1), cand)
|
|
1024
|
+
let maxLen: i32 = end - p
|
|
1025
|
+
if (maxLen > DEFLATE_MAX_MATCH) {
|
|
1026
|
+
maxLen = DEFLATE_MAX_MATCH
|
|
1027
|
+
}
|
|
1028
|
+
let best: i32 = this.minMatch - 1
|
|
1029
|
+
let bestDist: i32 = 0
|
|
1030
|
+
const limit: i32 = v - DEFLATE_WINDOW
|
|
1031
|
+
const nice: i32 = this.niceLength < maxLen ? this.niceLength : maxLen
|
|
1032
|
+
const lo: i32 = histStart + this.delta
|
|
1033
|
+
const mask: u32 = this.minMatch === 3 ? toU32(0xffffff) : ~toU32(0)
|
|
1034
|
+
let chain: i32 = this.maxChain
|
|
1035
|
+
while (cand >= limit && cand >= lo && cand < v && chain > 0) {
|
|
1036
|
+
const ci: i32 = cand - this.delta
|
|
1037
|
+
if (
|
|
1038
|
+
uncheckedGet(src, ci + best) === uncheckedGet(src, p + best) &&
|
|
1039
|
+
ci >= 0 &&
|
|
1040
|
+
ci <= 2147483639 &&
|
|
1041
|
+
((deflateLoad32(src, ci) ^ word) & mask) === 0
|
|
1042
|
+
) {
|
|
1043
|
+
const l: i32 = deflateMatchLength(src, ci, p, maxLen)
|
|
1044
|
+
if (l > best) {
|
|
1045
|
+
best = l
|
|
1046
|
+
bestDist = v - cand
|
|
1047
|
+
if (l >= nice) {
|
|
1048
|
+
break
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
cand = uncheckedGet(prev, cand & (DEFLATE_WINDOW - 1))
|
|
1053
|
+
chain -= 1
|
|
1054
|
+
}
|
|
1055
|
+
if (bestDist === 0 || best < this.minMatch) {
|
|
1056
|
+
return 0
|
|
1057
|
+
}
|
|
1058
|
+
// A three-byte match far back costs more than its three literals.
|
|
1059
|
+
if (best === 3 && bestDist > 4096) {
|
|
1060
|
+
return 0
|
|
1061
|
+
}
|
|
1062
|
+
return (best << 16) | bestDist
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/** Records `p` in the chains without searching; `p + 4 <= src.length`. */
|
|
1066
|
+
insert(src: u8[], p: i32): void {
|
|
1067
|
+
const head: i32[] = this.head
|
|
1068
|
+
const prev: i32[] = this.prev
|
|
1069
|
+
if (toI32(head.length) !== DEFLATE_HASH_SIZE || toI32(prev.length) !== DEFLATE_WINDOW) {
|
|
1070
|
+
panic("Deflater.insert: a table is not its size")
|
|
1071
|
+
}
|
|
1072
|
+
const word: u32 = deflateLoad32(src, p)
|
|
1073
|
+
const h: i32 =
|
|
1074
|
+
this.minMatch === 3
|
|
1075
|
+
? toI32(((word << 8) * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1076
|
+
: toI32((word * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1077
|
+
const v: i32 = p + this.delta
|
|
1078
|
+
uncheckedSet(prev, v & (DEFLATE_WINDOW - 1), uncheckedGet(head, h))
|
|
1079
|
+
uncheckedSet(head, h, v)
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/** Clears the block's symbols and frequencies. */
|
|
1083
|
+
startBlock(): void {
|
|
1084
|
+
this.litFreq.fill(0)
|
|
1085
|
+
this.distFreq.fill(0)
|
|
1086
|
+
this.count = 0
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/** Records the match `len`, `dist` as the block's next symbol. */
|
|
1090
|
+
addMatch(len: i32, dist: i32): void {
|
|
1091
|
+
const tokens: i32[] = this.tokens
|
|
1092
|
+
const n: i32 = this.count
|
|
1093
|
+
if (n < 0 || n >= toI32(tokens.length) || len < 3 || len > 258 || dist < 1 || dist > DEFLATE_WINDOW) {
|
|
1094
|
+
panic("Deflater.addMatch: a match outside the format")
|
|
1095
|
+
}
|
|
1096
|
+
uncheckedSet(tokens, n, (dist << 9) | (253 + len))
|
|
1097
|
+
this.count = n + 1
|
|
1098
|
+
const ls: i32 = uncheckedGet(this.lengthSymbol, len - 3)
|
|
1099
|
+
const lf: i32[] = this.litFreq
|
|
1100
|
+
uncheckedSet(lf, 257 + ls, uncheckedGet(lf, 257 + ls) + 1)
|
|
1101
|
+
const ds: i32 =
|
|
1102
|
+
dist <= 256
|
|
1103
|
+
? uncheckedGet(this.distSymbol, dist - 1)
|
|
1104
|
+
: uncheckedGet(this.distSymbol, ((dist - 1) >> 7) + 256)
|
|
1105
|
+
const df: i32[] = this.distFreq
|
|
1106
|
+
uncheckedSet(df, ds, uncheckedGet(df, ds) + 1)
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/** Records the literal `b` as the block's next symbol. */
|
|
1110
|
+
addLiteral(b: i32): void {
|
|
1111
|
+
const tokens: i32[] = this.tokens
|
|
1112
|
+
const n: i32 = this.count
|
|
1113
|
+
if (n < 0 || n >= toI32(tokens.length) || b < 0 || b > 255) {
|
|
1114
|
+
panic("Deflater.addLiteral: a literal outside the format")
|
|
1115
|
+
}
|
|
1116
|
+
uncheckedSet(tokens, n, b)
|
|
1117
|
+
this.count = n + 1
|
|
1118
|
+
const lf: i32[] = this.litFreq
|
|
1119
|
+
uncheckedSet(lf, b, uncheckedGet(lf, b) + 1)
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* Fills the block's symbols greedily from `start`, and answers where the
|
|
1124
|
+
* block ends: at `end`, or where the symbol buffer filled. The match
|
|
1125
|
+
* finder, the chains and the symbol bookkeeping are written out in this one
|
|
1126
|
+
* loop over locals, because this is the fast level's whole cost.
|
|
1127
|
+
*/
|
|
1128
|
+
collectGreedy(src: u8[], start: i32, end: i32, histStart: i32): i32 {
|
|
1129
|
+
this.startBlock()
|
|
1130
|
+
const head: i32[] = this.head
|
|
1131
|
+
const prev: i32[] = this.prev
|
|
1132
|
+
const tokens: i32[] = this.tokens
|
|
1133
|
+
const lf: i32[] = this.litFreq
|
|
1134
|
+
const df: i32[] = this.distFreq
|
|
1135
|
+
const lsym: i32[] = this.lengthSymbol
|
|
1136
|
+
const dsym: i32[] = this.distSymbol
|
|
1137
|
+
if (
|
|
1138
|
+
toI32(head.length) !== DEFLATE_HASH_SIZE ||
|
|
1139
|
+
toI32(prev.length) !== DEFLATE_WINDOW ||
|
|
1140
|
+
toI32(tokens.length) !== DEFLATE_BLOCK_TOKENS ||
|
|
1141
|
+
toI32(lf.length) < 288 ||
|
|
1142
|
+
toI32(df.length) < 32 ||
|
|
1143
|
+
toI32(lsym.length) < 256 ||
|
|
1144
|
+
toI32(dsym.length) < 512
|
|
1145
|
+
) {
|
|
1146
|
+
panic("Deflater.collectGreedy: a table is not its size")
|
|
1147
|
+
}
|
|
1148
|
+
const delta: i32 = this.delta
|
|
1149
|
+
const lo: i32 = histStart + delta
|
|
1150
|
+
const maxChain: i32 = this.maxChain
|
|
1151
|
+
const niceLength: i32 = this.niceLength
|
|
1152
|
+
const room: i32 = DEFLATE_BLOCK_TOKENS - 1
|
|
1153
|
+
const last: i32 = end - 4
|
|
1154
|
+
let n: i32 = 0
|
|
1155
|
+
let p: i32 = start
|
|
1156
|
+
while (p < end && n < room) {
|
|
1157
|
+
let best: i32 = 0
|
|
1158
|
+
let bestDist: i32 = 0
|
|
1159
|
+
if (p >= 0 && p <= last && p <= 2147483639) {
|
|
1160
|
+
const word: u32 = deflateLoad32(src, p)
|
|
1161
|
+
const h: i32 = toI32((word * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1162
|
+
const v: i32 = p + delta
|
|
1163
|
+
let cand: i32 = uncheckedGet(head, h)
|
|
1164
|
+
uncheckedSet(head, h, v)
|
|
1165
|
+
uncheckedSet(prev, v & (DEFLATE_WINDOW - 1), cand)
|
|
1166
|
+
const maxLen: i32 = end - p < DEFLATE_MAX_MATCH ? end - p : DEFLATE_MAX_MATCH
|
|
1167
|
+
const nice: i32 = niceLength < maxLen ? niceLength : maxLen
|
|
1168
|
+
const limit: i32 = v - DEFLATE_WINDOW
|
|
1169
|
+
let chain: i32 = maxChain
|
|
1170
|
+
while (cand >= limit && cand >= lo && cand < v && chain > 0) {
|
|
1171
|
+
const ci: i32 = cand - delta
|
|
1172
|
+
if (ci >= 0 && ci <= 2147483639 && deflateLoad32(src, ci) === word) {
|
|
1173
|
+
const l: i32 = 4 + deflateMatchLength(src, ci + 4, p + 4, maxLen - 4)
|
|
1174
|
+
if (l > best) {
|
|
1175
|
+
best = l
|
|
1176
|
+
bestDist = v - cand
|
|
1177
|
+
if (l >= nice) {
|
|
1178
|
+
break
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
cand = uncheckedGet(prev, cand & (DEFLATE_WINDOW - 1))
|
|
1183
|
+
chain -= 1
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
if (best >= 4) {
|
|
1187
|
+
uncheckedSet(tokens, n, (bestDist << 9) | (253 + best))
|
|
1188
|
+
n += 1
|
|
1189
|
+
const ls: i32 = 257 + uncheckedGet(lsym, best - 3)
|
|
1190
|
+
uncheckedSet(lf, ls, uncheckedGet(lf, ls) + 1)
|
|
1191
|
+
const ds: i32 =
|
|
1192
|
+
bestDist <= 256 ? uncheckedGet(dsym, bestDist - 1) : uncheckedGet(dsym, ((bestDist - 1) >> 7) + 256)
|
|
1193
|
+
uncheckedSet(df, ds, uncheckedGet(df, ds) + 1)
|
|
1194
|
+
// Every position the match covers goes into the chains.
|
|
1195
|
+
const stop: i32 = p + best
|
|
1196
|
+
let q: i32 = p + 1
|
|
1197
|
+
while (q < stop && q >= 0 && q <= last && q <= 2147483639) {
|
|
1198
|
+
const hq: i32 = toI32((deflateLoad32(src, q) * toU32(DEFLATE_HASH_MUL)) >>> 17)
|
|
1199
|
+
const vq: i32 = q + delta
|
|
1200
|
+
uncheckedSet(prev, vq & (DEFLATE_WINDOW - 1), uncheckedGet(head, hq))
|
|
1201
|
+
uncheckedSet(head, hq, vq)
|
|
1202
|
+
q += 1
|
|
1203
|
+
}
|
|
1204
|
+
p = stop
|
|
1205
|
+
} else {
|
|
1206
|
+
const b: i32 = toI32(uncheckedGet(src, p))
|
|
1207
|
+
uncheckedSet(tokens, n, b)
|
|
1208
|
+
n += 1
|
|
1209
|
+
uncheckedSet(lf, b, uncheckedGet(lf, b) + 1)
|
|
1210
|
+
p += 1
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
this.count = n
|
|
1214
|
+
return p
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
/**
|
|
1218
|
+
* Fills the block's symbols from `p`, deferring each match by a position
|
|
1219
|
+
* while the next one finds a longer one; answers where the block ends.
|
|
1220
|
+
*/
|
|
1221
|
+
collectLazy(src: u8[], start: i32, end: i32, histStart: i32): i32 {
|
|
1222
|
+
this.startBlock()
|
|
1223
|
+
let p: i32 = start
|
|
1224
|
+
const room: i32 = DEFLATE_BLOCK_TOKENS - 2
|
|
1225
|
+
while (p < end && this.count < room) {
|
|
1226
|
+
let m: i32 = 0
|
|
1227
|
+
if (p + 4 <= end) {
|
|
1228
|
+
m = this.longest(src, p, end, histStart)
|
|
1229
|
+
}
|
|
1230
|
+
if (m === 0) {
|
|
1231
|
+
this.addLiteral(toI32(uncheckedGet(src, p)))
|
|
1232
|
+
p += 1
|
|
1233
|
+
} else {
|
|
1234
|
+
let inserted: i32 = p + 1
|
|
1235
|
+
while (m >> 16 < this.lazyLength && p + 5 <= end && this.count < room) {
|
|
1236
|
+
const m2: i32 = this.longest(src, p + 1, end, histStart)
|
|
1237
|
+
inserted = p + 2
|
|
1238
|
+
if (m2 >> 16 > m >> 16) {
|
|
1239
|
+
this.addLiteral(toI32(uncheckedGet(src, p)))
|
|
1240
|
+
p += 1
|
|
1241
|
+
m = m2
|
|
1242
|
+
} else {
|
|
1243
|
+
break
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
const len: i32 = m >> 16
|
|
1247
|
+
this.addMatch(len, m & 0xffff)
|
|
1248
|
+
const stop: i32 = p + len
|
|
1249
|
+
let q: i32 = inserted
|
|
1250
|
+
const last: i32 = end - 4
|
|
1251
|
+
while (q < stop && q <= last) {
|
|
1252
|
+
this.insert(src, q)
|
|
1253
|
+
q += 1
|
|
1254
|
+
}
|
|
1255
|
+
p = stop
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
return p
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* The bits a stored rendering of `n` bytes takes from a bit buffer holding
|
|
1263
|
+
* `pending` bits: each piece of up to 65,535 bytes has three header bits,
|
|
1264
|
+
* the padding to a byte and four bytes of `LEN` / `NLEN`.
|
|
1265
|
+
*/
|
|
1266
|
+
storedBits(n: i32, pending: i32): i32 {
|
|
1267
|
+
let bits: i32 = 0
|
|
1268
|
+
let left: i32 = n
|
|
1269
|
+
let bc: i32 = pending
|
|
1270
|
+
let first: boolean = true
|
|
1271
|
+
while (first || left > 0) {
|
|
1272
|
+
first = false
|
|
1273
|
+
const take: i32 = left < DEFLATE_STORED_MAX ? left : DEFLATE_STORED_MAX
|
|
1274
|
+
const header: i32 = ((bc + 3 + 7) & ~7) - bc
|
|
1275
|
+
bits += header + 32 + 8 * take
|
|
1276
|
+
bc = 0
|
|
1277
|
+
left -= take
|
|
1278
|
+
}
|
|
1279
|
+
return bits
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
/**
|
|
1283
|
+
* Writes `src[start .. end)` as stored blocks, the last BFINAL when
|
|
1284
|
+
* `final`; answers the new position, or -1 without writing when it does
|
|
1285
|
+
* not fit in `out[op .. oe)`.
|
|
1286
|
+
*/
|
|
1287
|
+
writeStored(src: u8[], start: i32, end: i32, final: boolean, out: u8[], op: i32, oe: i32): i32 {
|
|
1288
|
+
const bits: i32 = this.storedBits(end - start, this.bitCount)
|
|
1289
|
+
if ((this.bitCount + bits + 7) >> 3 > oe - op) {
|
|
1290
|
+
return -1
|
|
1291
|
+
}
|
|
1292
|
+
let p: i32 = start
|
|
1293
|
+
let o: i32 = op
|
|
1294
|
+
let first: boolean = true
|
|
1295
|
+
while (first || p < end) {
|
|
1296
|
+
first = false
|
|
1297
|
+
const take: i32 = end - p < DEFLATE_STORED_MAX ? end - p : DEFLATE_STORED_MAX
|
|
1298
|
+
const last: boolean = p + take === end
|
|
1299
|
+
o = this.putBits(out, o, toI32(final && last ? 1 : 0), toI32(3))
|
|
1300
|
+
o = this.alignBits(out, o)
|
|
1301
|
+
deflateRoom(out, o, 4)
|
|
1302
|
+
uncheckedSet(out, o, toU8(take & 255))
|
|
1303
|
+
uncheckedSet(out, o + 1, toU8(take >> 8))
|
|
1304
|
+
uncheckedSet(out, o + 2, toU8(~take & 255))
|
|
1305
|
+
uncheckedSet(out, o + 3, toU8((~take >> 8) & 255))
|
|
1306
|
+
o += 4
|
|
1307
|
+
copyBytes(out, o, src, p, take)
|
|
1308
|
+
o += take
|
|
1309
|
+
p += take
|
|
1310
|
+
}
|
|
1311
|
+
return o
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
/**
|
|
1315
|
+
* Builds the run-length coded lengths of the dynamic header (§3.2.7) for
|
|
1316
|
+
* `hlit` literal/length and `hdist` distance lengths, and their
|
|
1317
|
+
* frequencies in `clFreq`.
|
|
1318
|
+
*/
|
|
1319
|
+
buildRle(hlit: i32, hdist: i32): void {
|
|
1320
|
+
const rle: i32[] = this.rle
|
|
1321
|
+
const freq: i32[] = this.clFreq
|
|
1322
|
+
const ll: i32[] = this.litLens
|
|
1323
|
+
const dl: i32[] = this.distLens
|
|
1324
|
+
if (toI32(rle.length) < 320 || toI32(freq.length) < 19 || hlit > 288 || hdist > 32) {
|
|
1325
|
+
panic("Deflater.buildRle: a header outside its scratch")
|
|
1326
|
+
}
|
|
1327
|
+
freq.fill(0)
|
|
1328
|
+
const total: i32 = hlit + hdist
|
|
1329
|
+
let n: i32 = 0
|
|
1330
|
+
let i: i32 = 0
|
|
1331
|
+
while (i < total) {
|
|
1332
|
+
const l: i32 = i < hlit ? uncheckedGet(ll, i) : uncheckedGet(dl, i - hlit)
|
|
1333
|
+
let run: i32 = 1
|
|
1334
|
+
while (
|
|
1335
|
+
i + run < total &&
|
|
1336
|
+
(i + run < hlit ? uncheckedGet(ll, i + run) : uncheckedGet(dl, i + run - hlit)) === l
|
|
1337
|
+
) {
|
|
1338
|
+
run += 1
|
|
1339
|
+
}
|
|
1340
|
+
i += run
|
|
1341
|
+
if (l === 0) {
|
|
1342
|
+
while (run >= 11) {
|
|
1343
|
+
const r: i32 = run < 138 ? run : 138
|
|
1344
|
+
uncheckedSet(rle, n, ((r - 11) << 8) | 18)
|
|
1345
|
+
n += 1
|
|
1346
|
+
freq[18] += 1
|
|
1347
|
+
run -= r
|
|
1348
|
+
}
|
|
1349
|
+
if (run >= 3) {
|
|
1350
|
+
uncheckedSet(rle, n, ((run - 3) << 8) | 17)
|
|
1351
|
+
n += 1
|
|
1352
|
+
freq[17] += 1
|
|
1353
|
+
run = 0
|
|
1354
|
+
}
|
|
1355
|
+
} else {
|
|
1356
|
+
uncheckedSet(rle, n, l)
|
|
1357
|
+
n += 1
|
|
1358
|
+
if (l >= 0 && l < 19) {
|
|
1359
|
+
uncheckedSet(freq, l, uncheckedGet(freq, l) + 1)
|
|
1360
|
+
}
|
|
1361
|
+
run -= 1
|
|
1362
|
+
while (run >= 3) {
|
|
1363
|
+
const r: i32 = run < 6 ? run : 6
|
|
1364
|
+
uncheckedSet(rle, n, ((r - 3) << 8) | 16)
|
|
1365
|
+
n += 1
|
|
1366
|
+
freq[16] += 1
|
|
1367
|
+
run -= r
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
while (run > 0) {
|
|
1371
|
+
uncheckedSet(rle, n, l)
|
|
1372
|
+
n += 1
|
|
1373
|
+
if (l >= 0 && l < 19) {
|
|
1374
|
+
uncheckedSet(freq, l, uncheckedGet(freq, l) + 1)
|
|
1375
|
+
}
|
|
1376
|
+
run -= 1
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
this.rleCount = n
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* Writes the block's symbols, `src[start .. end)`'s, as the smallest of a
|
|
1384
|
+
* dynamic, a fixed and a stored block; answers the new position, or -1
|
|
1385
|
+
* without writing when that does not fit in `out[op .. oe)`.
|
|
1386
|
+
*/
|
|
1387
|
+
writeBlock(src: u8[], start: i32, end: i32, final: boolean, out: u8[], op: i32, oe: i32): i32 {
|
|
1388
|
+
const lf: i32[] = this.litFreq
|
|
1389
|
+
const df: i32[] = this.distFreq
|
|
1390
|
+
lf[256] = 1
|
|
1391
|
+
deflateLengths(lf, 286, 15, this.litLens, this.scratch)
|
|
1392
|
+
deflateLengths(df, 30, 15, this.distLens, this.scratch)
|
|
1393
|
+
this.litLens[286] = 0
|
|
1394
|
+
this.litLens[287] = 0
|
|
1395
|
+
this.distLens[30] = 0
|
|
1396
|
+
this.distLens[31] = 0
|
|
1397
|
+
deflateCanonical(this.litLens, 286, this.litCodes, this.countScratch, this.nextScratch)
|
|
1398
|
+
deflateCanonical(this.distLens, 30, this.distCodes, this.countScratch, this.nextScratch)
|
|
1399
|
+
let hlit: i32 = 286
|
|
1400
|
+
while (hlit > 257 && this.litLens[hlit - 1] === 0) {
|
|
1401
|
+
hlit -= 1
|
|
1402
|
+
}
|
|
1403
|
+
let hdist: i32 = 30
|
|
1404
|
+
while (hdist > 1 && this.distLens[hdist - 1] === 0) {
|
|
1405
|
+
hdist -= 1
|
|
1406
|
+
}
|
|
1407
|
+
this.buildRle(hlit, hdist)
|
|
1408
|
+
deflateLengths(this.clFreq, 19, 7, this.clLens, this.scratch)
|
|
1409
|
+
deflateCanonical(this.clLens, 19, this.clCodes, this.countScratch, this.nextScratch)
|
|
1410
|
+
let hclen: i32 = 19
|
|
1411
|
+
while (hclen > 4 && this.clLens[deflateClOrder(hclen - 1)] === 0) {
|
|
1412
|
+
hclen -= 1
|
|
1413
|
+
}
|
|
1414
|
+
// The three sizes, exactly. Extra bits are the same in both codes.
|
|
1415
|
+
let extra: i32 = 0
|
|
1416
|
+
let dynBits: i32 = hclen * 3 + 17
|
|
1417
|
+
let fixBits: i32 = 3
|
|
1418
|
+
for (let s: i32 = 0; s < 286; s += 1) {
|
|
1419
|
+
const f: i32 = uncheckedGet(lf, s)
|
|
1420
|
+
dynBits += f * uncheckedGet(this.litLens, s)
|
|
1421
|
+
fixBits += f * uncheckedGet(this.fixedLitLens, s)
|
|
1422
|
+
if (s >= 257) {
|
|
1423
|
+
extra += f * uncheckedGet(this.lengthExtra, s - 257)
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
for (let d: i32 = 0; d < 30; d += 1) {
|
|
1427
|
+
const f: i32 = uncheckedGet(df, d)
|
|
1428
|
+
dynBits += f * uncheckedGet(this.distLens, d)
|
|
1429
|
+
fixBits += f * 5
|
|
1430
|
+
extra += f * uncheckedGet(this.distExtra, d)
|
|
1431
|
+
}
|
|
1432
|
+
for (let s: i32 = 0; s < 19; s += 1) {
|
|
1433
|
+
dynBits += this.clFreq[s] * this.clLens[s]
|
|
1434
|
+
}
|
|
1435
|
+
dynBits += 2 * this.clFreq[16] + 3 * this.clFreq[17] + 7 * this.clFreq[18]
|
|
1436
|
+
dynBits += extra
|
|
1437
|
+
fixBits += extra
|
|
1438
|
+
const storedBits: i32 = this.storedBits(end - start, this.bitCount)
|
|
1439
|
+
if (storedBits <= dynBits && storedBits <= fixBits) {
|
|
1440
|
+
return this.writeStored(src, start, end, final, out, op, oe)
|
|
1441
|
+
}
|
|
1442
|
+
const dynamic: boolean = dynBits < fixBits
|
|
1443
|
+
const bits: i32 = dynamic ? dynBits : fixBits
|
|
1444
|
+
if ((this.bitCount + bits + 7) >> 3 > oe - op) {
|
|
1445
|
+
return -1
|
|
1446
|
+
}
|
|
1447
|
+
let header: i32 = dynamic ? toI32(4) : toI32(2)
|
|
1448
|
+
if (final) {
|
|
1449
|
+
header += 1
|
|
1450
|
+
}
|
|
1451
|
+
let o: i32 = this.putBits(out, op, header, toI32(3))
|
|
1452
|
+
if (dynamic) {
|
|
1453
|
+
o = this.putBits(out, o, (hlit - 257) | ((hdist - 1) << 5) | ((hclen - 4) << 10), toI32(14))
|
|
1454
|
+
for (let i: i32 = 0; i < hclen; i += 1) {
|
|
1455
|
+
o = this.putBits(out, o, this.clLens[deflateClOrder(i)], toI32(3))
|
|
1456
|
+
}
|
|
1457
|
+
const rle: i32[] = this.rle
|
|
1458
|
+
const n: i32 = this.rleCount
|
|
1459
|
+
for (let i: i32 = 0; i < n && i < toI32(rle.length); i += 1) {
|
|
1460
|
+
const e: i32 = rle[i]
|
|
1461
|
+
const sym: i32 = e & 255
|
|
1462
|
+
if (sym < 0 || sym >= 19) {
|
|
1463
|
+
panic("Deflater.writeBlock: a code-length symbol outside 0 to 18")
|
|
1464
|
+
}
|
|
1465
|
+
o = this.putBits(out, o, this.clCodes[sym], this.clLens[sym])
|
|
1466
|
+
if (sym === 16) {
|
|
1467
|
+
o = this.putBits(out, o, e >> 8, toI32(2))
|
|
1468
|
+
} else if (sym === 17) {
|
|
1469
|
+
o = this.putBits(out, o, e >> 8, toI32(3))
|
|
1470
|
+
} else if (sym === 18) {
|
|
1471
|
+
o = this.putBits(out, o, e >> 8, toI32(7))
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
o = this.writeSymbols(this.litCodes, this.litLens, this.distCodes, this.distLens, out, o)
|
|
1475
|
+
} else {
|
|
1476
|
+
o = this.writeSymbols(
|
|
1477
|
+
this.fixedLitCodes,
|
|
1478
|
+
this.fixedLitLens,
|
|
1479
|
+
this.fixedDistCodes,
|
|
1480
|
+
this.fixedDistLens,
|
|
1481
|
+
out,
|
|
1482
|
+
o
|
|
1483
|
+
)
|
|
1484
|
+
}
|
|
1485
|
+
return o
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/**
|
|
1489
|
+
* Writes the block's symbols and its end-of-block code under the given
|
|
1490
|
+
* code into `out` at `op`; answers the new position. The room was checked
|
|
1491
|
+
* by the block's exact size.
|
|
1492
|
+
*/
|
|
1493
|
+
writeSymbols(lc: i32[], ll: i32[], dc: i32[], dl: i32[], out: u8[], op: i32): i32 {
|
|
1494
|
+
const tokens: i32[] = this.tokens
|
|
1495
|
+
const n: i32 = this.count
|
|
1496
|
+
const lsym: i32[] = this.lengthSymbol
|
|
1497
|
+
const lbase: i32[] = this.lengthBase
|
|
1498
|
+
const lextra: i32[] = this.lengthExtra
|
|
1499
|
+
const dsym: i32[] = this.distSymbol
|
|
1500
|
+
const dbase: i32[] = this.distBase
|
|
1501
|
+
const dextra: i32[] = this.distExtra
|
|
1502
|
+
if (
|
|
1503
|
+
toI32(lc.length) < 288 ||
|
|
1504
|
+
toI32(ll.length) < 288 ||
|
|
1505
|
+
toI32(dc.length) < 32 ||
|
|
1506
|
+
toI32(dl.length) < 32 ||
|
|
1507
|
+
n > toI32(tokens.length) ||
|
|
1508
|
+
toI32(lsym.length) < 256 ||
|
|
1509
|
+
toI32(lbase.length) < 29 ||
|
|
1510
|
+
toI32(lextra.length) < 29 ||
|
|
1511
|
+
toI32(dsym.length) < 512 ||
|
|
1512
|
+
toI32(dbase.length) < 30 ||
|
|
1513
|
+
toI32(dextra.length) < 30
|
|
1514
|
+
) {
|
|
1515
|
+
panic("Deflater.writeSymbols: a table is not its size")
|
|
1516
|
+
}
|
|
1517
|
+
let bb: u64 = this.bitBuf
|
|
1518
|
+
let bc: i32 = this.bitCount
|
|
1519
|
+
let o: i32 = op
|
|
1520
|
+
for (let i: i32 = 0; i < n; i += 1) {
|
|
1521
|
+
const t: i32 = uncheckedGet(tokens, i)
|
|
1522
|
+
if (t < 256) {
|
|
1523
|
+
bb = bb | (toU64(toU32(uncheckedGet(lc, t))) << toU64(bc))
|
|
1524
|
+
bc += uncheckedGet(ll, t)
|
|
1525
|
+
} else {
|
|
1526
|
+
const len3: i32 = (t & 511) - 256
|
|
1527
|
+
const dist: i32 = t >> 9
|
|
1528
|
+
const s: i32 = uncheckedGet(lsym, len3)
|
|
1529
|
+
bb = bb | (toU64(toU32(uncheckedGet(lc, 257 + s))) << toU64(bc))
|
|
1530
|
+
bc += uncheckedGet(ll, 257 + s)
|
|
1531
|
+
bb = bb | (toU64(toU32(len3 + 3 - uncheckedGet(lbase, s))) << toU64(bc))
|
|
1532
|
+
bc += uncheckedGet(lextra, s)
|
|
1533
|
+
if (bc >= 32) {
|
|
1534
|
+
deflateRoom(out, o, 4)
|
|
1535
|
+
uncheckedSet(out, o, toU8(bb & toU64(255)))
|
|
1536
|
+
uncheckedSet(out, o + 1, toU8((bb >> toU64(8)) & toU64(255)))
|
|
1537
|
+
uncheckedSet(out, o + 2, toU8((bb >> toU64(16)) & toU64(255)))
|
|
1538
|
+
uncheckedSet(out, o + 3, toU8((bb >> toU64(24)) & toU64(255)))
|
|
1539
|
+
bb = bb >> toU64(32)
|
|
1540
|
+
bc -= 32
|
|
1541
|
+
o += 4
|
|
1542
|
+
}
|
|
1543
|
+
const d: i32 =
|
|
1544
|
+
dist <= 256 ? uncheckedGet(dsym, dist - 1) : uncheckedGet(dsym, ((dist - 1) >> 7) + 256)
|
|
1545
|
+
bb = bb | (toU64(toU32(uncheckedGet(dc, d))) << toU64(bc))
|
|
1546
|
+
bc += uncheckedGet(dl, d)
|
|
1547
|
+
bb = bb | (toU64(toU32(dist - uncheckedGet(dbase, d))) << toU64(bc))
|
|
1548
|
+
bc += uncheckedGet(dextra, d)
|
|
1549
|
+
}
|
|
1550
|
+
if (bc >= 32) {
|
|
1551
|
+
deflateRoom(out, o, 4)
|
|
1552
|
+
uncheckedSet(out, o, toU8(bb & toU64(255)))
|
|
1553
|
+
uncheckedSet(out, o + 1, toU8((bb >> toU64(8)) & toU64(255)))
|
|
1554
|
+
uncheckedSet(out, o + 2, toU8((bb >> toU64(16)) & toU64(255)))
|
|
1555
|
+
uncheckedSet(out, o + 3, toU8((bb >> toU64(24)) & toU64(255)))
|
|
1556
|
+
bb = bb >> toU64(32)
|
|
1557
|
+
bc -= 32
|
|
1558
|
+
o += 4
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
this.bitBuf = bb
|
|
1562
|
+
this.bitCount = bc
|
|
1563
|
+
return this.putBits(out, o, lc[256], ll[256])
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
/**
|
|
1568
|
+
* One Huffman decoding table: the entries for every `bits`-bit prefix, and
|
|
1569
|
+
* for the codes longer than that, the count per length and the symbols in
|
|
1570
|
+
* canonical order that a bit-at-a-time decode walks (§3.2.2).
|
|
1571
|
+
*/
|
|
1572
|
+
export class InflateTable {
|
|
1573
|
+
/** `entries[peek]`: value << 16 | kind << 8 | extra << 4 | length. */
|
|
1574
|
+
readonly entries: i32[]
|
|
1575
|
+
/** The prefix the table indexes. */
|
|
1576
|
+
readonly bits: i32
|
|
1577
|
+
/** How many codes have each length 0 to 15. */
|
|
1578
|
+
readonly count: i32[]
|
|
1579
|
+
/** The symbols, ordered by code. */
|
|
1580
|
+
readonly symbols: i32[]
|
|
1581
|
+
|
|
1582
|
+
/** A table indexing `bits` bits, for an alphabet of up to `symbols` symbols. */
|
|
1583
|
+
constructor(bits: i32, symbols: i32) {
|
|
1584
|
+
this.bits = bits
|
|
1585
|
+
this.entries = new Array<i32>(1 << bits)
|
|
1586
|
+
this.count = new Array<i32>(16)
|
|
1587
|
+
this.symbols = new Array<i32>(symbols)
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
/** The kind of table `inflateBuild` builds: what each symbol decodes to. */
|
|
1592
|
+
const INF_TABLE_LITLEN: i32 = 0
|
|
1593
|
+
const INF_TABLE_DIST: i32 = 1
|
|
1594
|
+
const INF_TABLE_CODELEN: i32 = 2
|
|
1595
|
+
|
|
1596
|
+
/**
|
|
1597
|
+
* A DEFLATE decompressor: the decoding tables, the fixed code's, and the state
|
|
1598
|
+
* that lets `inflate` stop at the end of its input or output and resume.
|
|
1599
|
+
* Not shared between threads.
|
|
1600
|
+
*/
|
|
1601
|
+
export class Inflater {
|
|
1602
|
+
readonly lit: InflateTable
|
|
1603
|
+
readonly dist: InflateTable
|
|
1604
|
+
readonly codeLengths: InflateTable
|
|
1605
|
+
readonly fixedLit: InflateTable
|
|
1606
|
+
readonly fixedDist: InflateTable
|
|
1607
|
+
/** The lengths a dynamic header sends, literal/length then distance. */
|
|
1608
|
+
readonly lens: i32[]
|
|
1609
|
+
/** The order-indexed code-length code lengths. */
|
|
1610
|
+
readonly clLens: i32[]
|
|
1611
|
+
/** Scratch for building a table. */
|
|
1612
|
+
readonly offsets: i32[]
|
|
1613
|
+
readonly lengthBase: i32[]
|
|
1614
|
+
readonly lengthExtra: i32[]
|
|
1615
|
+
readonly distBase: i32[]
|
|
1616
|
+
readonly distExtra: i32[]
|
|
1617
|
+
/** Where `inflate` resumes: the block header, a stored block, a Huffman block, or done. */
|
|
1618
|
+
state: i32
|
|
1619
|
+
/** Whether the block being read is the final one. */
|
|
1620
|
+
last: boolean
|
|
1621
|
+
/** Whether the Huffman block uses the fixed code. */
|
|
1622
|
+
fixed: boolean
|
|
1623
|
+
/** Bytes of the current stored block still to copy. */
|
|
1624
|
+
storedLeft: i32
|
|
1625
|
+
/** Bits read but not consumed, low bit first, and how many. */
|
|
1626
|
+
bitBuf: u64
|
|
1627
|
+
bitCount: i32
|
|
1628
|
+
/** Where the last `inflate` stopped in its input and its output. */
|
|
1629
|
+
inPos: i32
|
|
1630
|
+
outPos: i32
|
|
1631
|
+
/** The input bytes the last `decompress` read, its final block included. */
|
|
1632
|
+
consumed: i32
|
|
1633
|
+
|
|
1634
|
+
/** Builds the tables, the fixed code's among them. */
|
|
1635
|
+
constructor() {
|
|
1636
|
+
this.lit = new InflateTable(INF_LIT_BITS, 288)
|
|
1637
|
+
this.dist = new InflateTable(INF_DIST_BITS, 32)
|
|
1638
|
+
this.codeLengths = new InflateTable(INF_CL_BITS, 19)
|
|
1639
|
+
this.fixedLit = new InflateTable(INF_LIT_BITS, 288)
|
|
1640
|
+
this.fixedDist = new InflateTable(INF_DIST_BITS, 32)
|
|
1641
|
+
this.lens = new Array<i32>(320)
|
|
1642
|
+
this.clLens = new Array<i32>(19)
|
|
1643
|
+
this.offsets = new Array<i32>(16)
|
|
1644
|
+
this.lengthBase = new Array<i32>(29)
|
|
1645
|
+
this.lengthExtra = new Array<i32>(29)
|
|
1646
|
+
this.distBase = new Array<i32>(32)
|
|
1647
|
+
this.distExtra = new Array<i32>(32)
|
|
1648
|
+
for (let s: i32 = 0; s < 29; s += 1) {
|
|
1649
|
+
this.lengthBase[s] = deflateLengthBase(s)
|
|
1650
|
+
this.lengthExtra[s] = deflateLengthExtra(s)
|
|
1651
|
+
}
|
|
1652
|
+
for (let d: i32 = 0; d < 30; d += 1) {
|
|
1653
|
+
this.distBase[d] = deflateDistBase(d)
|
|
1654
|
+
this.distExtra[d] = deflateDistExtra(d)
|
|
1655
|
+
}
|
|
1656
|
+
this.state = INF_S_BLOCK
|
|
1657
|
+
this.last = false
|
|
1658
|
+
this.fixed = false
|
|
1659
|
+
this.storedLeft = 0
|
|
1660
|
+
this.bitBuf = 0
|
|
1661
|
+
this.bitCount = 0
|
|
1662
|
+
this.inPos = 0
|
|
1663
|
+
this.outPos = 0
|
|
1664
|
+
this.consumed = 0
|
|
1665
|
+
for (let s: i32 = 0; s < 288; s += 1) {
|
|
1666
|
+
this.lens[s] = deflateFixedLitLength(s)
|
|
1667
|
+
}
|
|
1668
|
+
// The fixed distance code has 32 five-bit codes, 30 and 31 among them,
|
|
1669
|
+
// which decode as errors (§3.2.6).
|
|
1670
|
+
const fl: i32 = this.build(this.fixedLit, this.lens, toI32(0), toI32(288), INF_TABLE_LITLEN)
|
|
1671
|
+
for (let d: i32 = 0; d < 32; d += 1) {
|
|
1672
|
+
this.lens[d] = 5
|
|
1673
|
+
}
|
|
1674
|
+
const fd: i32 = this.build(this.fixedDist, this.lens, toI32(0), toI32(32), INF_TABLE_DIST)
|
|
1675
|
+
if (fl !== 0 || fd !== 0) {
|
|
1676
|
+
panic("Inflater: the fixed code did not build")
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/** Starts a new stream: the next `inflate` reads a first block header. */
|
|
1681
|
+
reset(): void {
|
|
1682
|
+
this.state = INF_S_BLOCK
|
|
1683
|
+
this.last = false
|
|
1684
|
+
this.fixed = false
|
|
1685
|
+
this.storedLeft = 0
|
|
1686
|
+
this.bitBuf = 0
|
|
1687
|
+
this.bitCount = 0
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* The table entry for symbol `s` of a table of `kind`.
|
|
1692
|
+
*/
|
|
1693
|
+
entryOf(kind: i32, s: i32, len: i32): i32 {
|
|
1694
|
+
if (kind === INF_TABLE_CODELEN) {
|
|
1695
|
+
return (s << 16) | len
|
|
1696
|
+
}
|
|
1697
|
+
if (kind === INF_TABLE_DIST) {
|
|
1698
|
+
if (s >= 30) {
|
|
1699
|
+
return (INF_INVALID << 8) | len
|
|
1700
|
+
}
|
|
1701
|
+
return (this.distBase[s] << 16) | (this.distExtra[s] << 4) | len
|
|
1702
|
+
}
|
|
1703
|
+
if (s < 256) {
|
|
1704
|
+
return (s << 16) | (INF_LITERAL << 8) | len
|
|
1705
|
+
}
|
|
1706
|
+
if (s === 256) {
|
|
1707
|
+
return (INF_END << 8) | len
|
|
1708
|
+
}
|
|
1709
|
+
if (s >= 286) {
|
|
1710
|
+
return (INF_INVALID << 8) | len
|
|
1711
|
+
}
|
|
1712
|
+
return (this.lengthBase[s - 257] << 16) | (INF_LENGTH << 8) | (this.lengthExtra[s - 257] << 4) | len
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* Builds `t` from the code lengths `lens[from .. from + n)`; answers 0, or
|
|
1717
|
+
* `DEFLATE_ERR_HUFFMAN` for an over-subscribed set or an incomplete one
|
|
1718
|
+
* (an incomplete set of a single one-bit code is allowed, as RFC 1951
|
|
1719
|
+
* §3.2.7 allows one distance code).
|
|
1720
|
+
*/
|
|
1721
|
+
build(t: InflateTable, lens: i32[], from: i32, n: i32, kind: i32): i32 {
|
|
1722
|
+
const count: i32[] = t.count
|
|
1723
|
+
const syms: i32[] = t.symbols
|
|
1724
|
+
const entries: i32[] = t.entries
|
|
1725
|
+
const offs: i32[] = this.offsets
|
|
1726
|
+
const bits: i32 = t.bits
|
|
1727
|
+
if (
|
|
1728
|
+
from < 0 ||
|
|
1729
|
+
n < 0 ||
|
|
1730
|
+
from > toI32(lens.length) - n ||
|
|
1731
|
+
n > toI32(syms.length) ||
|
|
1732
|
+
toI32(count.length) < 16 ||
|
|
1733
|
+
toI32(offs.length) < 16 ||
|
|
1734
|
+
toI32(entries.length) !== 1 << bits
|
|
1735
|
+
) {
|
|
1736
|
+
panic("Inflater.build: a table outside its scratch")
|
|
1737
|
+
}
|
|
1738
|
+
for (let l: i32 = 0; l < 16; l += 1) {
|
|
1739
|
+
count[l] = 0
|
|
1740
|
+
}
|
|
1741
|
+
for (let s: i32 = 0; s < n; s += 1) {
|
|
1742
|
+
const l: i32 = lens[from + s]
|
|
1743
|
+
if (l < 0 || l > 15) {
|
|
1744
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1745
|
+
}
|
|
1746
|
+
count[l] += 1
|
|
1747
|
+
}
|
|
1748
|
+
count[0] = 0
|
|
1749
|
+
// The Kraft sum: over-subscribed is an error; incomplete is allowed for
|
|
1750
|
+
// one one-bit code only.
|
|
1751
|
+
let left: i32 = 1
|
|
1752
|
+
let codes: i32 = 0
|
|
1753
|
+
for (let l: i32 = 1; l < 16; l += 1) {
|
|
1754
|
+
left = (left << 1) - count[l]
|
|
1755
|
+
codes += count[l]
|
|
1756
|
+
if (left < 0) {
|
|
1757
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (left > 0 && codes !== 0 && !(kind !== INF_TABLE_CODELEN && codes === 1 && count[1] === 1)) {
|
|
1761
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1762
|
+
}
|
|
1763
|
+
offs[1] = 0
|
|
1764
|
+
for (let l: i32 = 1; l < 15; l += 1) {
|
|
1765
|
+
offs[l + 1] = offs[l] + count[l]
|
|
1766
|
+
}
|
|
1767
|
+
for (let s: i32 = 0; s < n; s += 1) {
|
|
1768
|
+
const l: i32 = lens[from + s]
|
|
1769
|
+
if (l > 0 && l < 16) {
|
|
1770
|
+
const at: i32 = offs[l]
|
|
1771
|
+
if (at >= 0 && at < toI32(syms.length)) {
|
|
1772
|
+
syms[at] = s
|
|
1773
|
+
}
|
|
1774
|
+
offs[l] = at + 1
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
// A prefix whose code is longer than the table, or none at all, decodes
|
|
1778
|
+
// the slow way, which also finds an undefined code.
|
|
1779
|
+
const size: i32 = 1 << bits
|
|
1780
|
+
const slow: i32 = INF_SLOW << 8
|
|
1781
|
+
for (let i: i32 = 0; i < size; i += 1) {
|
|
1782
|
+
uncheckedSet(entries, i, slow)
|
|
1783
|
+
}
|
|
1784
|
+
let code: i32 = 0
|
|
1785
|
+
let k: i32 = 0
|
|
1786
|
+
for (let l: i32 = 1; l <= bits && l < 16; l += 1) {
|
|
1787
|
+
const codesHere: i32 = uncheckedGet(count, l)
|
|
1788
|
+
for (let c: i32 = 0; c < codesHere; c += 1) {
|
|
1789
|
+
if (k >= 0 && k < toI32(syms.length)) {
|
|
1790
|
+
const e: i32 = this.entryOf(kind, syms[k], l)
|
|
1791
|
+
const step: i32 = 1 << l
|
|
1792
|
+
for (let r: i32 = deflateReverse(code, l); r < size; r += step) {
|
|
1793
|
+
uncheckedSet(entries, r, e)
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
k += 1
|
|
1797
|
+
code += 1
|
|
1798
|
+
}
|
|
1799
|
+
code = code << 1
|
|
1800
|
+
}
|
|
1801
|
+
return 0
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
/**
|
|
1805
|
+
* Decodes the symbol at the bottom of `bb`, holding `bc` valid bits, one
|
|
1806
|
+
* bit at a time from the counts (§3.2.2): answers the table entry of the
|
|
1807
|
+
* symbol with its true code length, or -1 when the bits run out before a
|
|
1808
|
+
* code ends (`bc` too small), or -2 when no code matches.
|
|
1809
|
+
*/
|
|
1810
|
+
slowDecode(t: InflateTable, kind: i32, bb: u64, bc: i32): i32 {
|
|
1811
|
+
const count: i32[] = t.count
|
|
1812
|
+
const syms: i32[] = t.symbols
|
|
1813
|
+
let code: i32 = 0
|
|
1814
|
+
let first: i32 = 0
|
|
1815
|
+
let index: i32 = 0
|
|
1816
|
+
let b: u64 = bb
|
|
1817
|
+
for (let l: i32 = 1; l < 16 && l < toI32(count.length); l += 1) {
|
|
1818
|
+
if (l > bc) {
|
|
1819
|
+
return -1
|
|
1820
|
+
}
|
|
1821
|
+
code = code | toI32(b & toU64(1))
|
|
1822
|
+
b = b >> toU64(1)
|
|
1823
|
+
const c: i32 = count[l]
|
|
1824
|
+
if (code - c < first) {
|
|
1825
|
+
const at: i32 = index + (code - first)
|
|
1826
|
+
if (at < 0 || at >= toI32(syms.length)) {
|
|
1827
|
+
return -2
|
|
1828
|
+
}
|
|
1829
|
+
return this.entryOf(kind, syms[at], l)
|
|
1830
|
+
}
|
|
1831
|
+
index += c
|
|
1832
|
+
first = (first + c) << 1
|
|
1833
|
+
code = code << 1
|
|
1834
|
+
}
|
|
1835
|
+
return -2
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
/** Reads bytes of `src` into the bit buffer from `inPos` while it has room and `end` allows. */
|
|
1839
|
+
fill(src: u8[], end: i32): void {
|
|
1840
|
+
let bb: u64 = this.bitBuf
|
|
1841
|
+
let bc: i32 = this.bitCount
|
|
1842
|
+
let ip: i32 = this.inPos
|
|
1843
|
+
if (ip < 0 || end > toI32(src.length)) {
|
|
1844
|
+
panic("Inflater.fill: a window outside its input")
|
|
1845
|
+
}
|
|
1846
|
+
while (bc <= 56 && ip < end) {
|
|
1847
|
+
bb = bb | (toU64(uncheckedGet(src, ip)) << toU64(bc))
|
|
1848
|
+
ip += 1
|
|
1849
|
+
bc += 8
|
|
1850
|
+
}
|
|
1851
|
+
this.bitBuf = bb
|
|
1852
|
+
this.bitCount = bc
|
|
1853
|
+
this.inPos = ip
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
/** The low `n` bits of the bit buffer, consumed; the caller has checked that `n` are there. */
|
|
1857
|
+
take(n: i32): i32 {
|
|
1858
|
+
const v: i32 = toI32(this.bitBuf & ((toU64(1) << toU64(n)) - toU64(1)))
|
|
1859
|
+
this.bitBuf = this.bitBuf >> toU64(n)
|
|
1860
|
+
this.bitCount = this.bitCount - n
|
|
1861
|
+
return v
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* Gives back the whole bytes of the bit buffer to the input, after dropping
|
|
1866
|
+
* the bits to the next byte boundary: where a stored block's `LEN`, or the
|
|
1867
|
+
* framing after the final block, begins.
|
|
1868
|
+
*/
|
|
1869
|
+
unread(): void {
|
|
1870
|
+
const drop: i32 = this.bitCount & 7
|
|
1871
|
+
this.bitBuf = this.bitBuf >> toU64(drop)
|
|
1872
|
+
this.bitCount = this.bitCount - drop
|
|
1873
|
+
this.inPos = this.inPos - (this.bitCount >> 3)
|
|
1874
|
+
this.bitBuf = 0
|
|
1875
|
+
this.bitCount = 0
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
/**
|
|
1879
|
+
* Reads a dynamic block's header (§3.2.7) from the bit buffer and `src`,
|
|
1880
|
+
* and builds its tables. Answers 0, `INFLATE_NEED_INPUT` when the input ran
|
|
1881
|
+
* out first (nothing is consumed then: the caller rewinds), or an error.
|
|
1882
|
+
*/
|
|
1883
|
+
readDynamic(src: u8[], end: i32): i32 {
|
|
1884
|
+
this.fill(src, end)
|
|
1885
|
+
if (this.bitCount < 14) {
|
|
1886
|
+
return INFLATE_NEED_INPUT
|
|
1887
|
+
}
|
|
1888
|
+
const hlit: i32 = this.take(toI32(5)) + 257
|
|
1889
|
+
const hdist: i32 = this.take(toI32(5)) + 1
|
|
1890
|
+
const hclen: i32 = this.take(toI32(4)) + 4
|
|
1891
|
+
if (hlit > 286 || hdist > 30) {
|
|
1892
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1893
|
+
}
|
|
1894
|
+
const cl: i32[] = this.clLens
|
|
1895
|
+
for (let i: i32 = 0; i < 19; i += 1) {
|
|
1896
|
+
cl[deflateClOrder(i)] = 0
|
|
1897
|
+
}
|
|
1898
|
+
for (let i: i32 = 0; i < hclen; i += 1) {
|
|
1899
|
+
this.fill(src, end)
|
|
1900
|
+
if (this.bitCount < 3) {
|
|
1901
|
+
return INFLATE_NEED_INPUT
|
|
1902
|
+
}
|
|
1903
|
+
cl[deflateClOrder(i)] = this.take(toI32(3))
|
|
1904
|
+
}
|
|
1905
|
+
const r: i32 = this.build(this.codeLengths, cl, toI32(0), toI32(19), INF_TABLE_CODELEN)
|
|
1906
|
+
if (r !== 0) {
|
|
1907
|
+
return r
|
|
1908
|
+
}
|
|
1909
|
+
const lens: i32[] = this.lens
|
|
1910
|
+
const entries: i32[] = this.codeLengths.entries
|
|
1911
|
+
const total: i32 = hlit + hdist
|
|
1912
|
+
let i: i32 = 0
|
|
1913
|
+
while (i < total) {
|
|
1914
|
+
this.fill(src, end)
|
|
1915
|
+
const e: i32 = entries[toI32(this.bitBuf & toU64(127))]
|
|
1916
|
+
if (((e >> 8) & 7) === INF_SLOW) {
|
|
1917
|
+
// Only an incomplete code-length code leaves a prefix unfilled.
|
|
1918
|
+
return this.bitCount >= 7 ? DEFLATE_ERR_SYMBOL : INFLATE_NEED_INPUT
|
|
1919
|
+
}
|
|
1920
|
+
const l: i32 = e & 15
|
|
1921
|
+
if (l > this.bitCount) {
|
|
1922
|
+
return INFLATE_NEED_INPUT
|
|
1923
|
+
}
|
|
1924
|
+
this.take(l)
|
|
1925
|
+
const sym: i32 = e >> 16
|
|
1926
|
+
if (sym < 16) {
|
|
1927
|
+
if (i < 0 || i >= toI32(lens.length)) {
|
|
1928
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1929
|
+
}
|
|
1930
|
+
lens[i] = sym
|
|
1931
|
+
i += 1
|
|
1932
|
+
} else {
|
|
1933
|
+
let rep: i32 = 0
|
|
1934
|
+
let value: i32 = 0
|
|
1935
|
+
if (sym === 16) {
|
|
1936
|
+
if (i === 0) {
|
|
1937
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1938
|
+
}
|
|
1939
|
+
if (this.bitCount < 2) {
|
|
1940
|
+
return INFLATE_NEED_INPUT
|
|
1941
|
+
}
|
|
1942
|
+
value = lens[i - 1]
|
|
1943
|
+
rep = toI32(3) + this.take(toI32(2))
|
|
1944
|
+
} else if (sym === 17) {
|
|
1945
|
+
if (this.bitCount < 3) {
|
|
1946
|
+
return INFLATE_NEED_INPUT
|
|
1947
|
+
}
|
|
1948
|
+
rep = toI32(3) + this.take(toI32(3))
|
|
1949
|
+
} else {
|
|
1950
|
+
if (this.bitCount < 7) {
|
|
1951
|
+
return INFLATE_NEED_INPUT
|
|
1952
|
+
}
|
|
1953
|
+
rep = toI32(11) + this.take(toI32(7))
|
|
1954
|
+
}
|
|
1955
|
+
if (i + rep > total) {
|
|
1956
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1957
|
+
}
|
|
1958
|
+
for (let k: i32 = 0; k < rep && i < toI32(lens.length); k += 1) {
|
|
1959
|
+
lens[i] = value
|
|
1960
|
+
i += 1
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
if (lens[256] === 0) {
|
|
1965
|
+
return DEFLATE_ERR_HUFFMAN
|
|
1966
|
+
}
|
|
1967
|
+
const rl: i32 = this.build(this.lit, lens, toI32(0), hlit, INF_TABLE_LITLEN)
|
|
1968
|
+
if (rl !== 0) {
|
|
1969
|
+
return rl
|
|
1970
|
+
}
|
|
1971
|
+
return this.build(this.dist, lens, hlit, hdist, INF_TABLE_DIST)
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
/**
|
|
1975
|
+
* Decodes from `src[ip .. inEnd)` into `out[op .. outEnd)`, resuming where
|
|
1976
|
+
* the last call stopped; a match may reach back to `histStart`. `more`
|
|
1977
|
+
* says whether input may follow `inEnd`: with it, running out is
|
|
1978
|
+
* `INFLATE_NEED_INPUT` (every byte up to `inPos` is used, and the bit
|
|
1979
|
+
* buffer keeps what it read ahead), without it `DEFLATE_ERR_TRUNCATED`.
|
|
1980
|
+
* Answers `INFLATE_DONE` once the final block has ended, with `inPos` the
|
|
1981
|
+
* first byte after it; `INFLATE_NEED_OUTPUT` when the next symbol does not
|
|
1982
|
+
* fit; or a negative `DEFLATE_ERR_*`. `inPos` and `outPos` say where it
|
|
1983
|
+
* stopped. Windows outside their arrays panic.
|
|
1984
|
+
*/
|
|
1985
|
+
inflate(
|
|
1986
|
+
src: u8[],
|
|
1987
|
+
ip: i32,
|
|
1988
|
+
inEnd: i32,
|
|
1989
|
+
more: boolean,
|
|
1990
|
+
out: u8[],
|
|
1991
|
+
op: i32,
|
|
1992
|
+
outEnd: i32,
|
|
1993
|
+
histStart: i32
|
|
1994
|
+
): i32 {
|
|
1995
|
+
if (ip < 0 || ip > inEnd || inEnd > toI32(src.length)) {
|
|
1996
|
+
panic("Inflater.inflate: an input window outside its array")
|
|
1997
|
+
}
|
|
1998
|
+
if (histStart < 0 || histStart > op || op > outEnd || outEnd > toI32(out.length)) {
|
|
1999
|
+
panic("Inflater.inflate: an output window outside its array")
|
|
2000
|
+
}
|
|
2001
|
+
this.inPos = ip
|
|
2002
|
+
this.outPos = op
|
|
2003
|
+
const r: i32 = this.step(src, inEnd, more, out, outEnd, histStart)
|
|
2004
|
+
// Whole bytes the bit buffer read ahead go back to the input, so that a
|
|
2005
|
+
// caller may drop everything before `inPos`.
|
|
2006
|
+
const back: i32 = this.bitCount >> 3
|
|
2007
|
+
this.inPos = this.inPos - back
|
|
2008
|
+
this.bitCount = this.bitCount - 8 * back
|
|
2009
|
+
this.bitBuf = this.bitBuf & ((toU64(1) << toU64(this.bitCount)) - toU64(1))
|
|
2010
|
+
return r
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/** `inflate`'s state machine, once its windows are checked. */
|
|
2014
|
+
step(src: u8[], inEnd: i32, more: boolean, out: u8[], outEnd: i32, histStart: i32): i32 {
|
|
2015
|
+
while (true) {
|
|
2016
|
+
const s: i32 = this.state
|
|
2017
|
+
if (s === INF_S_DONE) {
|
|
2018
|
+
return INFLATE_DONE
|
|
2019
|
+
}
|
|
2020
|
+
if (s === INF_S_BLOCK) {
|
|
2021
|
+
if (this.last) {
|
|
2022
|
+
this.unread()
|
|
2023
|
+
this.state = INF_S_DONE
|
|
2024
|
+
return INFLATE_DONE
|
|
2025
|
+
}
|
|
2026
|
+
const saveBuf: u64 = this.bitBuf
|
|
2027
|
+
const saveCount: i32 = this.bitCount
|
|
2028
|
+
const savePos: i32 = this.inPos
|
|
2029
|
+
this.fill(src, inEnd)
|
|
2030
|
+
if (this.bitCount < 3) {
|
|
2031
|
+
this.bitBuf = saveBuf
|
|
2032
|
+
this.bitCount = saveCount
|
|
2033
|
+
this.inPos = savePos
|
|
2034
|
+
return more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2035
|
+
}
|
|
2036
|
+
const header: i32 = this.take(toI32(3))
|
|
2037
|
+
const type: i32 = header >> 1
|
|
2038
|
+
if (type === 0) {
|
|
2039
|
+
this.unread()
|
|
2040
|
+
if (inEnd - this.inPos < 4) {
|
|
2041
|
+
this.bitBuf = saveBuf
|
|
2042
|
+
this.bitCount = saveCount
|
|
2043
|
+
this.inPos = savePos
|
|
2044
|
+
return more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2045
|
+
}
|
|
2046
|
+
const at: i32 = this.inPos
|
|
2047
|
+
const len: i32 = toI32(uncheckedGet(src, at)) | (toI32(uncheckedGet(src, at + 1)) << 8)
|
|
2048
|
+
const nlen: i32 = toI32(uncheckedGet(src, at + 2)) | (toI32(uncheckedGet(src, at + 3)) << 8)
|
|
2049
|
+
if ((len ^ 0xffff) !== nlen) {
|
|
2050
|
+
return DEFLATE_ERR_STORED_LENGTH
|
|
2051
|
+
}
|
|
2052
|
+
this.inPos = at + 4
|
|
2053
|
+
this.storedLeft = len
|
|
2054
|
+
this.last = (header & 1) !== 0
|
|
2055
|
+
this.state = INF_S_STORED
|
|
2056
|
+
} else if (type === 1) {
|
|
2057
|
+
this.last = (header & 1) !== 0
|
|
2058
|
+
this.fixed = true
|
|
2059
|
+
this.state = INF_S_HUFF
|
|
2060
|
+
} else if (type === 2) {
|
|
2061
|
+
const r: i32 = this.readDynamic(src, inEnd)
|
|
2062
|
+
if (r === INFLATE_NEED_INPUT) {
|
|
2063
|
+
this.bitBuf = saveBuf
|
|
2064
|
+
this.bitCount = saveCount
|
|
2065
|
+
this.inPos = savePos
|
|
2066
|
+
return more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2067
|
+
}
|
|
2068
|
+
if (r !== 0) {
|
|
2069
|
+
return r
|
|
2070
|
+
}
|
|
2071
|
+
this.last = (header & 1) !== 0
|
|
2072
|
+
this.fixed = false
|
|
2073
|
+
this.state = INF_S_HUFF
|
|
2074
|
+
} else {
|
|
2075
|
+
return DEFLATE_ERR_BLOCK_TYPE
|
|
2076
|
+
}
|
|
2077
|
+
} else if (s === INF_S_STORED) {
|
|
2078
|
+
let n: i32 = this.storedLeft
|
|
2079
|
+
const inAvail: i32 = inEnd - this.inPos
|
|
2080
|
+
const outAvail: i32 = outEnd - this.outPos
|
|
2081
|
+
if (n > inAvail) {
|
|
2082
|
+
n = inAvail
|
|
2083
|
+
}
|
|
2084
|
+
if (n > outAvail) {
|
|
2085
|
+
n = outAvail
|
|
2086
|
+
}
|
|
2087
|
+
copyBytes(out, this.outPos, src, this.inPos, n)
|
|
2088
|
+
this.inPos += n
|
|
2089
|
+
this.outPos += n
|
|
2090
|
+
this.storedLeft -= n
|
|
2091
|
+
if (this.storedLeft > 0) {
|
|
2092
|
+
if (this.outPos === outEnd) {
|
|
2093
|
+
return INFLATE_NEED_OUTPUT
|
|
2094
|
+
}
|
|
2095
|
+
return more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2096
|
+
}
|
|
2097
|
+
this.state = INF_S_BLOCK
|
|
2098
|
+
} else {
|
|
2099
|
+
const r: i32 = this.huffman(src, inEnd, more, out, outEnd, histStart)
|
|
2100
|
+
if (r !== 0) {
|
|
2101
|
+
return r
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
/**
|
|
2108
|
+
* The Huffman block loop: decodes symbols until the end of the block
|
|
2109
|
+
* (answers 0, the state back at a block header), or until the input or
|
|
2110
|
+
* the output runs short or the stream is malformed (answers that code).
|
|
2111
|
+
*/
|
|
2112
|
+
huffman(src: u8[], inEnd: i32, more: boolean, out: u8[], outEnd: i32, histStart: i32): i32 {
|
|
2113
|
+
const lt: InflateTable = this.fixed ? this.fixedLit : this.lit
|
|
2114
|
+
const dt: InflateTable = this.fixed ? this.fixedDist : this.dist
|
|
2115
|
+
const le: i32[] = lt.entries
|
|
2116
|
+
const de: i32[] = dt.entries
|
|
2117
|
+
if (toI32(le.length) !== 1 << INF_LIT_BITS || toI32(de.length) !== 1 << INF_DIST_BITS) {
|
|
2118
|
+
panic("Inflater.huffman: a table is not its size")
|
|
2119
|
+
}
|
|
2120
|
+
const litMask: u64 = toU64((1 << INF_LIT_BITS) - 1)
|
|
2121
|
+
const distMask: u64 = toU64((1 << INF_DIST_BITS) - 1)
|
|
2122
|
+
let bb: u64 = this.bitBuf
|
|
2123
|
+
let bc: i32 = this.bitCount
|
|
2124
|
+
let ip: i32 = this.inPos
|
|
2125
|
+
let op: i32 = this.outPos
|
|
2126
|
+
let status: i32 = 0
|
|
2127
|
+
while (true) {
|
|
2128
|
+
// The fast loop: while eight bytes of input and the longest match
|
|
2129
|
+
// with eight bytes of slack fit, no symbol can run short, so none is
|
|
2130
|
+
// checked for it. A symbol the fast loop does not decode (an end of
|
|
2131
|
+
// block, a long code, an error) is rewound and left to the careful
|
|
2132
|
+
// step below, which then hands back here.
|
|
2133
|
+
while (ip >= 0 && ip <= inEnd - 8 && ip <= 2147483639 && op >= 0 && op <= outEnd - 274) {
|
|
2134
|
+
const fBb: u64 = bb
|
|
2135
|
+
const fBc: i32 = bc
|
|
2136
|
+
const fIp: i32 = ip
|
|
2137
|
+
bb = bb | (deflateLoad64(src, ip) << toU64(bc))
|
|
2138
|
+
ip += (63 - bc) >> 3
|
|
2139
|
+
bc = bc | 56
|
|
2140
|
+
let e: i32 = uncheckedGet(le, toI32(bb & litMask))
|
|
2141
|
+
if ((e & 0x700) === 0) {
|
|
2142
|
+
// A literal; with at least 41 bits left, so may the next two be.
|
|
2143
|
+
const n: i32 = e & 15
|
|
2144
|
+
bb = bb >> toU64(n)
|
|
2145
|
+
bc -= n
|
|
2146
|
+
uncheckedSet(out, op, toU8(e >> 16))
|
|
2147
|
+
op += 1
|
|
2148
|
+
e = uncheckedGet(le, toI32(bb & litMask))
|
|
2149
|
+
if ((e & 0x700) === 0) {
|
|
2150
|
+
const n2: i32 = e & 15
|
|
2151
|
+
bb = bb >> toU64(n2)
|
|
2152
|
+
bc -= n2
|
|
2153
|
+
uncheckedSet(out, op, toU8(e >> 16))
|
|
2154
|
+
op += 1
|
|
2155
|
+
e = uncheckedGet(le, toI32(bb & litMask))
|
|
2156
|
+
if ((e & 0x700) === 0) {
|
|
2157
|
+
const n3: i32 = e & 15
|
|
2158
|
+
bb = bb >> toU64(n3)
|
|
2159
|
+
bc -= n3
|
|
2160
|
+
uncheckedSet(out, op, toU8(e >> 16))
|
|
2161
|
+
op += 1
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
continue
|
|
2165
|
+
}
|
|
2166
|
+
if (((e >> 8) & 7) !== INF_LENGTH) {
|
|
2167
|
+
bb = fBb
|
|
2168
|
+
bc = fBc
|
|
2169
|
+
ip = fIp
|
|
2170
|
+
break
|
|
2171
|
+
}
|
|
2172
|
+
const n: i32 = e & 15
|
|
2173
|
+
bb = bb >> toU64(n)
|
|
2174
|
+
const lx: i32 = (e >> 4) & 15
|
|
2175
|
+
const len: i32 = (e >> 16) + toI32(bb & ((toU64(1) << toU64(lx)) - toU64(1)))
|
|
2176
|
+
bb = bb >> toU64(lx)
|
|
2177
|
+
const d: i32 = uncheckedGet(de, toI32(bb & distMask))
|
|
2178
|
+
if ((d & 0x700) !== 0) {
|
|
2179
|
+
bb = fBb
|
|
2180
|
+
bc = fBc
|
|
2181
|
+
ip = fIp
|
|
2182
|
+
break
|
|
2183
|
+
}
|
|
2184
|
+
const dn: i32 = d & 15
|
|
2185
|
+
const dx: i32 = (d >> 4) & 15
|
|
2186
|
+
bb = bb >> toU64(dn)
|
|
2187
|
+
const dist: i32 = (d >> 16) + toI32(bb & ((toU64(1) << toU64(dx)) - toU64(1)))
|
|
2188
|
+
bb = bb >> toU64(dx)
|
|
2189
|
+
bc -= n + lx + dn + dx
|
|
2190
|
+
if (dist > op - histStart) {
|
|
2191
|
+
status = DEFLATE_ERR_DISTANCE
|
|
2192
|
+
break
|
|
2193
|
+
}
|
|
2194
|
+
let from: i32 = op - dist
|
|
2195
|
+
const stop: i32 = op + len
|
|
2196
|
+
if (dist >= 8) {
|
|
2197
|
+
while (op < stop && from >= 0 && from <= 2147483639 && op >= 0 && op <= 2147483639) {
|
|
2198
|
+
deflateStore64(out, op, deflateLoad64(out, from))
|
|
2199
|
+
op += 8
|
|
2200
|
+
from += 8
|
|
2201
|
+
}
|
|
2202
|
+
op = stop
|
|
2203
|
+
} else {
|
|
2204
|
+
while (op < stop && from >= 0 && from < op) {
|
|
2205
|
+
uncheckedSet(out, op, uncheckedGet(out, from))
|
|
2206
|
+
op += 1
|
|
2207
|
+
from += 1
|
|
2208
|
+
}
|
|
2209
|
+
op = stop
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
if (status !== 0) {
|
|
2213
|
+
break
|
|
2214
|
+
}
|
|
2215
|
+
const sBb: u64 = bb
|
|
2216
|
+
const sBc: i32 = bc
|
|
2217
|
+
const sIp: i32 = ip
|
|
2218
|
+
// Refill to at least 56 bits: every symbol, its extra bits, its
|
|
2219
|
+
// distance and their extra bits take at most 48.
|
|
2220
|
+
if (ip >= 0 && ip <= 2147483639 && ip + 8 <= inEnd) {
|
|
2221
|
+
bb = bb | (deflateLoad64(src, ip) << toU64(bc))
|
|
2222
|
+
ip += (63 - bc) >> 3
|
|
2223
|
+
bc = bc | 56
|
|
2224
|
+
} else {
|
|
2225
|
+
while (bc <= 56 && ip < inEnd) {
|
|
2226
|
+
bb = bb | (toU64(uncheckedGet(src, ip)) << toU64(bc))
|
|
2227
|
+
ip += 1
|
|
2228
|
+
bc += 8
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
let e: i32 = uncheckedGet(le, toI32(bb & litMask))
|
|
2232
|
+
let kind: i32 = (e >> 8) & 7
|
|
2233
|
+
if (kind === INF_SLOW) {
|
|
2234
|
+
e = this.slowDecode(lt, INF_TABLE_LITLEN, bb, bc)
|
|
2235
|
+
if (e === -1) {
|
|
2236
|
+
status = INFLATE_NEED_INPUT
|
|
2237
|
+
} else if (e < 0) {
|
|
2238
|
+
status = DEFLATE_ERR_SYMBOL
|
|
2239
|
+
}
|
|
2240
|
+
kind = (e >> 8) & 7
|
|
2241
|
+
}
|
|
2242
|
+
if (status === 0 && (e & 15) > bc) {
|
|
2243
|
+
status = INFLATE_NEED_INPUT
|
|
2244
|
+
}
|
|
2245
|
+
if (status !== 0) {
|
|
2246
|
+
if (status === INFLATE_NEED_INPUT) {
|
|
2247
|
+
bb = sBb
|
|
2248
|
+
bc = sBc
|
|
2249
|
+
ip = sIp
|
|
2250
|
+
if (!more) {
|
|
2251
|
+
status = DEFLATE_ERR_TRUNCATED
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
break
|
|
2255
|
+
}
|
|
2256
|
+
const n: i32 = e & 15
|
|
2257
|
+
bb = bb >> toU64(n)
|
|
2258
|
+
bc -= n
|
|
2259
|
+
if (kind === INF_LITERAL) {
|
|
2260
|
+
if (op >= outEnd) {
|
|
2261
|
+
bb = sBb
|
|
2262
|
+
bc = sBc
|
|
2263
|
+
ip = sIp
|
|
2264
|
+
status = INFLATE_NEED_OUTPUT
|
|
2265
|
+
break
|
|
2266
|
+
}
|
|
2267
|
+
uncheckedSet(out, op, toU8(e >> 16))
|
|
2268
|
+
op += 1
|
|
2269
|
+
} else if (kind === INF_LENGTH) {
|
|
2270
|
+
const lx: i32 = (e >> 4) & 15
|
|
2271
|
+
if (lx > bc) {
|
|
2272
|
+
bb = sBb
|
|
2273
|
+
bc = sBc
|
|
2274
|
+
ip = sIp
|
|
2275
|
+
status = more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2276
|
+
break
|
|
2277
|
+
}
|
|
2278
|
+
const len: i32 = (e >> 16) + toI32(bb & ((toU64(1) << toU64(lx)) - toU64(1)))
|
|
2279
|
+
bb = bb >> toU64(lx)
|
|
2280
|
+
bc -= lx
|
|
2281
|
+
let d: i32 = uncheckedGet(de, toI32(bb & distMask))
|
|
2282
|
+
if (((d >> 8) & 7) === INF_SLOW) {
|
|
2283
|
+
d = this.slowDecode(dt, INF_TABLE_DIST, bb, bc)
|
|
2284
|
+
if (d === -1) {
|
|
2285
|
+
bb = sBb
|
|
2286
|
+
bc = sBc
|
|
2287
|
+
ip = sIp
|
|
2288
|
+
status = more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2289
|
+
break
|
|
2290
|
+
}
|
|
2291
|
+
if (d < 0) {
|
|
2292
|
+
status = DEFLATE_ERR_SYMBOL
|
|
2293
|
+
break
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
if (((d >> 8) & 7) === INF_INVALID) {
|
|
2297
|
+
status = DEFLATE_ERR_SYMBOL
|
|
2298
|
+
break
|
|
2299
|
+
}
|
|
2300
|
+
const dn: i32 = d & 15
|
|
2301
|
+
const dx: i32 = (d >> 4) & 15
|
|
2302
|
+
if (dn + dx > bc) {
|
|
2303
|
+
bb = sBb
|
|
2304
|
+
bc = sBc
|
|
2305
|
+
ip = sIp
|
|
2306
|
+
status = more ? INFLATE_NEED_INPUT : DEFLATE_ERR_TRUNCATED
|
|
2307
|
+
break
|
|
2308
|
+
}
|
|
2309
|
+
bb = bb >> toU64(dn)
|
|
2310
|
+
const dist: i32 = (d >> 16) + toI32(bb & ((toU64(1) << toU64(dx)) - toU64(1)))
|
|
2311
|
+
bb = bb >> toU64(dx)
|
|
2312
|
+
bc -= dn + dx
|
|
2313
|
+
if (dist > op - histStart) {
|
|
2314
|
+
status = DEFLATE_ERR_DISTANCE
|
|
2315
|
+
break
|
|
2316
|
+
}
|
|
2317
|
+
if (len > outEnd - op) {
|
|
2318
|
+
bb = sBb
|
|
2319
|
+
bc = sBc
|
|
2320
|
+
ip = sIp
|
|
2321
|
+
status = INFLATE_NEED_OUTPUT
|
|
2322
|
+
break
|
|
2323
|
+
}
|
|
2324
|
+
let from: i32 = op - dist
|
|
2325
|
+
const stop: i32 = op + len
|
|
2326
|
+
if (dist >= 8 && stop + 8 <= outEnd) {
|
|
2327
|
+
// Eight bytes at a time; a copy may run up to seven bytes past
|
|
2328
|
+
// `stop`, inside `outEnd`, which the next symbol overwrites.
|
|
2329
|
+
while (op < stop && from >= 0 && from <= 2147483639 && op >= 0 && op <= 2147483639) {
|
|
2330
|
+
deflateStore64(out, op, deflateLoad64(out, from))
|
|
2331
|
+
op += 8
|
|
2332
|
+
from += 8
|
|
2333
|
+
}
|
|
2334
|
+
op = stop
|
|
2335
|
+
} else {
|
|
2336
|
+
while (op < stop) {
|
|
2337
|
+
uncheckedSet(out, op, uncheckedGet(out, from))
|
|
2338
|
+
op += 1
|
|
2339
|
+
from += 1
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
} else if (kind === INF_END) {
|
|
2343
|
+
this.state = INF_S_BLOCK
|
|
2344
|
+
break
|
|
2345
|
+
} else {
|
|
2346
|
+
status = DEFLATE_ERR_SYMBOL
|
|
2347
|
+
break
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
this.bitBuf = bb
|
|
2351
|
+
this.bitCount = bc
|
|
2352
|
+
this.inPos = ip
|
|
2353
|
+
this.outPos = op
|
|
2354
|
+
return status
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
/**
|
|
2358
|
+
* Decompresses the raw DEFLATE stream `src[off .. off + len)` into `out`
|
|
2359
|
+
* from `at`, writing at most `limit` bytes and never past `out`'s end, and
|
|
2360
|
+
* answers where the output ends; or `DEFLATE_ERR_OUTPUT_LIMIT` when the
|
|
2361
|
+
* stream holds more, `DEFLATE_ERR_TRAILING` when bytes follow its final
|
|
2362
|
+
* block, or another negative `DEFLATE_ERR_*` for a malformed stream. A
|
|
2363
|
+
* window outside its array, or a negative `limit`, panics. Allocates
|
|
2364
|
+
* nothing.
|
|
2365
|
+
*/
|
|
2366
|
+
decompress(src: u8[], off: i32, len: i32, out: u8[], at: i32, limit: i32): i32 {
|
|
2367
|
+
deflateWindow("Inflater.decompress", src, off, len)
|
|
2368
|
+
deflateWindow("Inflater.decompress", out, at, 0)
|
|
2369
|
+
if (limit < 0) {
|
|
2370
|
+
panic("Inflater.decompress: a negative limit")
|
|
2371
|
+
}
|
|
2372
|
+
const room: i32 = toI32(out.length) - at
|
|
2373
|
+
const end: i32 = at + (limit < room ? limit : room)
|
|
2374
|
+
this.reset()
|
|
2375
|
+
const r: i32 = this.inflate(src, off, off + len, false, out, at, end, at)
|
|
2376
|
+
this.consumed = this.inPos - off
|
|
2377
|
+
if (r === INFLATE_NEED_OUTPUT) {
|
|
2378
|
+
return DEFLATE_ERR_OUTPUT_LIMIT
|
|
2379
|
+
}
|
|
2380
|
+
if (r !== INFLATE_DONE) {
|
|
2381
|
+
return r
|
|
2382
|
+
}
|
|
2383
|
+
if (this.inPos !== off + len) {
|
|
2384
|
+
return DEFLATE_ERR_TRAILING
|
|
2385
|
+
}
|
|
2386
|
+
return this.outPos
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
/**
|
|
2391
|
+
* `Deflater.compress` at `level`, building the compressor for this call
|
|
2392
|
+
* alone: 330 KB allocated and filled each time, so keep a `Deflater` for
|
|
2393
|
+
* anything repeated.
|
|
2394
|
+
*/
|
|
2395
|
+
export const deflateCompress = (src: u8[], off: i32, len: i32, out: u8[], at: i32, level: i32): i32 =>
|
|
2396
|
+
new Deflater(level).compress(src, off, len, out, at)
|
|
2397
|
+
|
|
2398
|
+
/** `Inflater.decompress`, building the decompressor for this call alone. */
|
|
2399
|
+
export const deflateDecompress = (src: u8[], off: i32, len: i32, out: u8[], at: i32, limit: i32): i32 =>
|
|
2400
|
+
new Inflater().decompress(src, off, len, out, at, limit)
|