UNPKG

@substrate-system/fflate

Version:

High performance (de)compression in an 8kB package

4 lines 186 kB
{ "version": 3, "sources": ["../src/index.ts"], "sourcesContent": ["// DEFLATE is a complex format; to read this code, you should probably check\n// the RFC first:\n// https://tools.ietf.org/html/rfc1951\n// You may also wish to take a look at the guide I made about this program:\n// https://gist.github.com/101arrowz/253f31eb5abc3d9275ab943003ffecad\n\n// Some of the following code is similar to that of UZIP.js:\n// https://github.com/photopea/UZIP.js\n// However, the vast majority of the codebase has diverged from UZIP.js to\n// increase performance and reduce bundle size.\n\n// Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint\n// is better for memory in most engines (I *think*).\n\nimport wk from './node-worker';\n\n// aliases for shorter compressed code (most minifers don't do this)\nconst u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;\n\n// fixed length extra bits\nconst fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]);\n\n// fixed distance extra bits\nconst fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]);\n\n// code length index map\nconst clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);\n\n// get base, reverse index map from extra bits\nconst freb = (eb: Uint8Array, start: number) => {\n const b = new u16(31);\n for (let i = 0; i < 31; ++i) {\n b[i] = start += 1 << eb[i - 1];\n }\n // numbers here are at max 18 bits\n const r = new i32(b[30]);\n for (let i = 1; i < 30; ++i) {\n for (let j = b[i]; j < b[i + 1]; ++j) {\n r[j] = ((j - b[i]) << 5) | i;\n }\n }\n return { b, r };\n}\n\nconst { b: fl, r: revfl } = freb(fleb, 2);\n// we can ignore the fact that the other numbers are wrong; they never happen anyway\nfl[28] = 258, revfl[258] = 28;\nconst { b: fd, r: revfd } = freb(fdeb, 0);\n\n// map of value to reverse (assuming 16 bits)\nconst rev = new u16(32768);\nfor (let i = 0; i < 32768; ++i) {\n // reverse table algorithm from SO\n let x = ((i & 0xAAAA) >> 1) | ((i & 0x5555) << 1);\n x = ((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2);\n x = ((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4);\n rev[i] = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)) >> 1;\n}\n\n// create huffman tree from u8 \"map\": index -> code length for code index\n// mb (max bits) must be at most 15\n// TODO: optimize/split up?\nconst hMap = ((cd: Uint8Array, mb: number, r: 0 | 1) => {\n const s = cd.length;\n // index\n let i = 0;\n // u16 \"map\": index -> # of codes with bit length = index\n const l = new u16(mb);\n // length of cd must be 288 (total # of codes)\n for (; i < s; ++i) {\n if (cd[i]) ++l[cd[i] - 1];\n }\n // u16 \"map\": index -> minimum code for bit length = index\n const le = new u16(mb);\n for (i = 1; i < mb; ++i) {\n le[i] = (le[i - 1] + l[i - 1]) << 1;\n }\n let co: Uint16Array;\n if (r) {\n // u16 \"map\": index -> number of actual bits, symbol for code\n co = new u16(1 << mb);\n // bits to remove for reverser\n const rvb = 15 - mb;\n for (i = 0; i < s; ++i) {\n // ignore 0 lengths\n if (cd[i]) {\n // num encoding both symbol and bits read\n const sv = (i << 4) | cd[i];\n // free bits\n const r = mb - cd[i];\n // start value\n let v = le[cd[i] - 1]++ << r;\n // m is end value\n for (const m = v | ((1 << r) - 1); v <= m; ++v) {\n // every 16 bit value starting with the code yields the same result\n co[rev[v] >> rvb] = sv;\n }\n }\n }\n } else {\n co = new u16(s);\n for (i = 0; i < s; ++i) {\n if (cd[i]) {\n co[i] = rev[le[cd[i] - 1]++] >> (15 - cd[i]);\n }\n }\n }\n return co;\n});\n\n// fixed length tree\nconst flt = new u8(288);\nfor (let i = 0; i < 144; ++i) flt[i] = 8;\nfor (let i = 144; i < 256; ++i) flt[i] = 9;\nfor (let i = 256; i < 280; ++i) flt[i] = 7;\nfor (let i = 280; i < 288; ++i) flt[i] = 8;\n// fixed distance tree\nconst fdt = new u8(32);\nfor (let i = 0; i < 32; ++i) fdt[i] = 5;\n// fixed length map\nconst flm = /*#__PURE__*/ hMap(flt, 9, 0), flrm = /*#__PURE__*/ hMap(flt, 9, 1);\n// fixed distance map\nconst fdm = /*#__PURE__*/ hMap(fdt, 5, 0), fdrm = /*#__PURE__*/ hMap(fdt, 5, 1);\n\n// find max of array\nconst max = (a: Uint8Array | number[]) => {\n let m = a[0];\n for (let i = 1; i < a.length; ++i) {\n if (a[i] > m) m = a[i];\n }\n return m;\n};\n\n// read d, starting at bit p and mask with m\nconst bits = (d: Uint8Array, p: number, m: number) => {\n const o = (p / 8) | 0;\n return ((d[o] | (d[o + 1] << 8)) >> (p & 7)) & m;\n}\n\n// read d, starting at bit p continuing for at least 16 bits\nconst bits16 = (d: Uint8Array, p: number) => {\n const o = (p / 8) | 0;\n return ((d[o] | (d[o + 1] << 8) | (d[o + 2] << 16)) >> (p & 7));\n}\n\n// get end of byte\nconst shft = (p: number) => ((p + 7) / 8) | 0;\n\n// typed array slice - allows garbage collector to free original reference,\n// while being more compatible than .slice\nconst slc = (v: Uint8Array, s: number, e?: number) => {\n if (s == null || s < 0) s = 0;\n if (e == null || e > v.length) e = v.length;\n // can't use .constructor in case user-supplied\n return new u8(v.subarray(s, e));\n}\n\n// inflate state\ntype InflateState = {\n // lmap\n l?: Uint16Array;\n // dmap\n d?: Uint16Array;\n // lbits\n m?: number;\n // dbits\n n?: number;\n // final\n f?: number;\n // pos\n p?: number;\n // byte\n b?: number;\n // lstchk\n i: number;\n};\n\n/**\n * Codes for errors generated within this library\n */\nexport const FlateErrorCode = {\n UnexpectedEOF: 0,\n InvalidBlockType: 1,\n InvalidLengthLiteral: 2,\n InvalidDistance: 3,\n StreamFinished: 4,\n NoStreamHandler: 5,\n InvalidHeader: 6,\n NoCallback: 7,\n InvalidUTF8: 8,\n ExtraFieldTooLong: 9,\n InvalidDate: 10,\n FilenameTooLong: 11,\n StreamFinishing: 12,\n InvalidZipData: 13,\n UnknownCompressionMethod: 14\n} as const;\n\n// error codes\nconst ec = [\n 'unexpected EOF',\n 'invalid block type',\n 'invalid length/literal',\n 'invalid distance',\n 'stream finished',\n 'no stream handler',\n , // determined by compression function\n 'no callback',\n 'invalid UTF-8 data',\n 'extra field too long',\n 'date not in range 1980-2099',\n 'filename too long',\n 'stream finishing',\n 'invalid zip data'\n // determined by unknown compression method\n];\n\n/**\n * An error generated within this library\n */\nexport interface FlateError extends Error {\n /**\n * The code associated with this error\n */\n code: number;\n};\n\nconst err = (ind: number, msg?: string | 0, nt?: 1) => {\n const e: Partial<FlateError> = new Error(msg || ec[ind]);\n e.code = ind;\n if (Error.captureStackTrace) Error.captureStackTrace(e, err);\n if (!nt) throw e;\n return e as FlateError;\n}\n\n// expands raw DEFLATE data\nconst inflt = (dat: Uint8Array, st: InflateState, buf?: Uint8Array, dict?: Uint8Array) => {\n // source length dict length\n const sl = dat.length, dl = dict ? dict.length : 0;\n if (!sl || st.f && !st.l) return buf || new u8(0);\n const noBuf = !buf;\n // have to estimate size\n const resize = noBuf || st.i != 2;\n // no state\n const noSt = st.i;\n // Assumes roughly 33% compression ratio average\n if (noBuf) buf = new u8(sl * 3);\n // ensure buffer can fit at least l elements\n const cbuf = (l: number) => {\n let bl = buf.length;\n // need to increase size to fit\n if (l > bl) {\n // Double or set to necessary, whichever is greater\n const nbuf = new u8(Math.max(bl * 2, l));\n nbuf.set(buf);\n buf = nbuf;\n }\n };\n // last chunk bitpos bytes\n let final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;\n // total bits\n const tbts = sl * 8;\n do {\n if (!lm) {\n // BFINAL - this is only 1 when last chunk is next\n final = bits(dat, pos, 1);\n // type: 0 = no compression, 1 = fixed huffman, 2 = dynamic huffman\n const type = bits(dat, pos + 1, 3);\n pos += 3;\n if (!type) {\n // go to end of byte boundary\n const s = shft(pos) + 4, l = dat[s - 4] | (dat[s - 3] << 8), t = s + l;\n if (t > sl) {\n if (noSt) err(0);\n break;\n }\n // ensure size\n if (resize) cbuf(bt + l);\n // Copy over uncompressed data\n buf.set(dat.subarray(s, t), bt);\n // Get new bitpos, update byte count\n st.b = bt += l, st.p = pos = t * 8, st.f = final;\n continue;\n }\n else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;\n else if (type == 2) {\n // literal lengths\n const hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;\n const tl = hLit + bits(dat, pos + 5, 31) + 1;\n pos += 14;\n // length+distance tree\n const ldt = new u8(tl);\n // code length tree\n const clt = new u8(19);\n for (let i = 0; i < hcLen; ++i) {\n // use index map to get real code\n clt[clim[i]] = bits(dat, pos + i * 3, 7);\n }\n pos += hcLen * 3;\n // code lengths bits\n const clb = max(clt), clbmsk = (1 << clb) - 1;\n // code lengths map\n const clm = hMap(clt, clb, 1);\n for (let i = 0; i < tl;) {\n const r = clm[bits(dat, pos, clbmsk)];\n // bits read\n pos += r & 15;\n // symbol\n const s = r >> 4;\n // code length to copy\n if (s < 16) {\n ldt[i++] = s;\n } else {\n // copy count\n let c = 0, n = 0;\n if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];\n else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;\n else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;\n while (n--) ldt[i++] = c;\n }\n }\n // length tree distance tree\n const lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);\n // max length bits\n lbt = max(lt)\n // max dist bits\n dbt = max(dt);\n lm = hMap(lt, lbt, 1);\n dm = hMap(dt, dbt, 1);\n } else err(1);\n if (pos > tbts) {\n if (noSt) err(0);\n break;\n }\n }\n // Make sure the buffer can hold this + the largest possible addition\n // Maximum chunk size (practically, theoretically infinite) is 2^17\n if (resize) cbuf(bt + 131072);\n const lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;\n let lpos = pos;\n for (;; lpos = pos) {\n // bits read, code\n const c = lm[bits16(dat, pos) & lms], sym = c >> 4;\n pos += c & 15;\n if (pos > tbts) {\n if (noSt) err(0);\n break;\n }\n if (!c) err(2);\n if (sym < 256) buf[bt++] = sym;\n else if (sym == 256) {\n lpos = pos, lm = null;\n break;\n } else {\n let add = sym - 254;\n // no extra bits needed if less\n if (sym > 264) {\n // index\n const i = sym - 257, b = fleb[i];\n add = bits(dat, pos, (1 << b) - 1) + fl[i];\n pos += b;\n }\n // dist\n const d = dm[bits16(dat, pos) & dms], dsym = d >> 4;\n if (!d) err(3);\n pos += d & 15;\n let dt = fd[dsym];\n if (dsym > 3) {\n const b = fdeb[dsym];\n dt += bits16(dat, pos) & (1 << b) - 1, pos += b;\n }\n if (pos > tbts) {\n if (noSt) err(0);\n break;\n }\n if (resize) cbuf(bt + 131072);\n const end = bt + add;\n if (bt < dt) {\n const shift = dl - dt, dend = Math.min(dt, end);\n if (shift + bt < 0) err(3);\n for (; bt < dend; ++bt) buf[bt] = dict[shift + bt];\n }\n for (; bt < end; ++bt) buf[bt] = buf[bt - dt];\n }\n }\n st.l = lm, st.p = lpos, st.b = bt, st.f = final;\n if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;\n } while (!final)\n // don't reallocate for streams or user buffers\n return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);\n}\n\n// starting at p, write the minimum number of bits that can hold v to d\nconst wbits = (d: Uint8Array, p: number, v: number) => {\n v <<= p & 7;\n const o = (p / 8) | 0;\n d[o] |= v;\n d[o + 1] |= v >> 8;\n}\n\n// starting at p, write the minimum number of bits (>8) that can hold v to d\nconst wbits16 = (d: Uint8Array, p: number, v: number) => {\n v <<= p & 7;\n const o = (p / 8) | 0;\n d[o] |= v;\n d[o + 1] |= v >> 8;\n d[o + 2] |= v >> 16;\n}\n\ntype HuffNode = {\n // symbol\n s: number;\n // frequency\n f: number;\n // left child\n l?: HuffNode;\n // right child\n r?: HuffNode;\n};\n\n// creates code lengths from a frequency table\nconst hTree = (d: Uint16Array, mb: number) => {\n // Need extra info to make a tree\n const t: HuffNode[] = [];\n for (let i = 0; i < d.length; ++i) {\n if (d[i]) t.push({ s: i, f: d[i] });\n }\n const s = t.length;\n const t2 = t.slice();\n if (!s) return { t: et, l: 0 };\n if (s == 1) {\n const v = new u8(t[0].s + 1);\n v[t[0].s] = 1;\n return { t: v, l: 1 };\n }\n t.sort((a, b) => a.f - b.f);\n // after i2 reaches last ind, will be stopped\n // freq must be greater than largest possible number of symbols\n t.push({ s: -1, f: 25001 });\n let l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;\n t[0] = { s: -1, f: l.f + r.f, l, r };\n // efficient algorithm from UZIP.js\n // i0 is lookbehind, i2 is lookahead - after processing two low-freq\n // symbols that combined have high freq, will start processing i2 (high-freq,\n // non-composite) symbols instead\n // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/\n while (i1 != s - 1) {\n l = t[t[i0].f < t[i2].f ? i0++ : i2++];\n r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];\n t[i1++] = { s: -1, f: l.f + r.f, l, r };\n }\n let maxSym = t2[0].s;\n for (let i = 1; i < s; ++i) {\n if (t2[i].s > maxSym) maxSym = t2[i].s;\n }\n // code lengths\n const tr = new u16(maxSym + 1);\n // max bits in tree\n let mbt = ln(t[i1 - 1], tr, 0);\n if (mbt > mb) {\n // more algorithms from UZIP.js\n // TODO: find out how this code works (debt)\n // ind debt\n let i = 0, dt = 0;\n // left cost\n const lft = mbt - mb, cst = 1 << lft;\n t2.sort((a, b) => tr[b.s] - tr[a.s] || a.f - b.f);\n for (; i < s; ++i) {\n const i2 = t2[i].s;\n if (tr[i2] > mb) {\n dt += cst - (1 << (mbt - tr[i2]));\n tr[i2] = mb;\n } else break;\n }\n dt >>= lft;\n while (dt > 0) {\n const i2 = t2[i].s;\n if (tr[i2] < mb) dt -= 1 << (mb - tr[i2]++ - 1);\n else ++i;\n }\n for (; i >= 0 && dt; --i) {\n const i2 = t2[i].s;\n if (tr[i2] == mb) {\n --tr[i2];\n ++dt;\n }\n }\n mbt = mb;\n }\n return { t: new u8(tr), l: mbt };\n}\n// get the max length and assign length codes\nconst ln = (n: HuffNode, l: Uint16Array, d: number): number => {\n return n.s == -1\n ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1))\n : (l[n.s] = d);\n}\n\n// length codes generation\nconst lc = (c: Uint8Array) => {\n let s = c.length;\n // Note that the semicolon was intentional\n while (s && !c[--s]);\n const cl = new u16(++s);\n // ind num streak\n let cli = 0, cln = c[0], cls = 1;\n const w = (v: number) => { cl[cli++] = v; }\n for (let i = 1; i <= s; ++i) {\n if (c[i] == cln && i != s)\n ++cls;\n else {\n if (!cln && cls > 2) {\n for (; cls > 138; cls -= 138) w(32754);\n if (cls > 2) {\n w(cls > 10 ? ((cls - 11) << 5) | 28690 : ((cls - 3) << 5) | 12305);\n cls = 0;\n }\n } else if (cls > 3) {\n w(cln), --cls;\n for (; cls > 6; cls -= 6) w(8304);\n if (cls > 2) w(((cls - 3) << 5) | 8208), cls = 0;\n }\n while (cls--) w(cln);\n cls = 1;\n cln = c[i];\n }\n }\n return { c: cl.subarray(0, cli), n: s };\n}\n\n// calculate the length of output from tree, code lengths\nconst clen = (cf: Uint16Array, cl: Uint8Array) => {\n let l = 0;\n for (let i = 0; i < cl.length; ++i) l += cf[i] * cl[i];\n return l;\n}\n\n// writes a fixed block\n// returns the new bit pos\nconst wfblk = (out: Uint8Array, pos: number, dat: Uint8Array) => {\n // no need to write 00 as type: TypedArray defaults to 0\n const s = dat.length;\n const o = shft(pos + 2);\n out[o] = s & 255;\n out[o + 1] = s >> 8;\n out[o + 2] = out[o] ^ 255;\n out[o + 3] = out[o + 1] ^ 255;\n for (let i = 0; i < s; ++i) out[o + i + 4] = dat[i];\n return (o + 4 + s) * 8;\n}\n\n// writes a block\nconst wblk = (dat: Uint8Array, out: Uint8Array, final: number, syms: Int32Array, lf: Uint16Array, df: Uint16Array, eb: number, li: number, bs: number, bl: number, p: number) => {\n wbits(out, p++, final);\n ++lf[256];\n const { t: dlt, l: mlb } = hTree(lf, 15);\n const { t: ddt, l: mdb } = hTree(df, 15);\n const { c: lclt, n: nlc } = lc(dlt);\n const { c: lcdt, n: ndc } = lc(ddt);\n const lcfreq = new u16(19);\n for (let i = 0; i < lclt.length; ++i) ++lcfreq[lclt[i] & 31];\n for (let i = 0; i < lcdt.length; ++i) ++lcfreq[lcdt[i] & 31];\n const { t: lct, l: mlcb } = hTree(lcfreq, 7);\n let nlcc = 19;\n for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc);\n const flen = (bl + 5) << 3;\n const ftlen = clen(lf, flt) + clen(df, fdt) + eb;\n const dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18];\n if (bs >= 0 && flen <= ftlen && flen <= dtlen) return wfblk(out, p, dat.subarray(bs, bs + bl));\n let lm: Uint16Array, ll: Uint8Array, dm: Uint16Array, dl: Uint8Array;\n wbits(out, p, 1 + (dtlen < ftlen as unknown as number)), p += 2;\n if (dtlen < ftlen) {\n lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;\n const llm = hMap(lct, mlcb, 0);\n wbits(out, p, nlc - 257);\n wbits(out, p + 5, ndc - 1);\n wbits(out, p + 10, nlcc - 4);\n p += 14;\n for (let i = 0; i < nlcc; ++i) wbits(out, p + 3 * i, lct[clim[i]]);\n p += 3 * nlcc;\n const lcts = [lclt, lcdt];\n for (let it = 0; it < 2; ++it) {\n const clct = lcts[it];\n for (let i = 0; i < clct.length; ++i) {\n const len = clct[i] & 31;\n wbits(out, p, llm[len]), p += lct[len];\n if (len > 15) wbits(out, p, (clct[i] >> 5) & 127), p += clct[i] >> 12;\n }\n }\n } else {\n lm = flm, ll = flt, dm = fdm, dl = fdt;\n }\n for (let i = 0; i < li; ++i) {\n const sym = syms[i];\n if (sym > 255) {\n const len = (sym >> 18) & 31;\n wbits16(out, p, lm[len + 257]), p += ll[len + 257];\n if (len > 7) wbits(out, p, (sym >> 23) & 31), p += fleb[len];\n const dst = sym & 31;\n wbits16(out, p, dm[dst]), p += dl[dst];\n if (dst > 3) wbits16(out, p, (sym >> 5) & 8191), p += fdeb[dst];\n } else {\n wbits16(out, p, lm[sym]), p += ll[sym];\n }\n }\n wbits16(out, p, lm[256]);\n return p + ll[256];\n}\n\n// deflate options (nice << 13) | chain\nconst deo = /*#__PURE__*/ new i32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);\n\n// empty\nconst et = /*#__PURE__*/new u8(0);\n\ntype DeflateState = {\n // head\n h?: Uint16Array;\n // prev\n p?: Uint16Array;\n // index\n i?: number;\n // end index\n z?: number;\n // wait index\n w?: number;\n // remainder byte info\n r?: number;\n // last chunk\n l: number;\n};\n\n// compresses data into a raw DEFLATE buffer\nconst dflt = (dat: Uint8Array, lvl: number, plvl: number, pre: number, post: number, st: DeflateState) => {\n const s = st.z || dat.length;\n const o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7000)) + post);\n // writing to this writes to the output buffer\n const w = o.subarray(pre, o.length - post);\n const lst = st.l;\n let pos = (st.r || 0) & 7;\n if (lvl) {\n if (pos) w[0] = st.r >> 3;\n const opt = deo[lvl - 1];\n const n = opt >> 13, c = opt & 8191;\n const msk = (1 << plvl) - 1;\n // prev 2-byte val map curr 2-byte val map\n const prev = st.p || new u16(32768), head = st.h || new u16(msk + 1);\n const bs1 = Math.ceil(plvl / 3), bs2 = 2 * bs1;\n const hsh = (i: number) => (dat[i] ^ (dat[i + 1] << bs1) ^ (dat[i + 2] << bs2)) & msk;\n // 24576 is an arbitrary number of maximum symbols per block\n // 424 buffer for last block\n const syms = new i32(25000);\n // length/literal freq distance freq\n const lf = new u16(288), df = new u16(32);\n // l/lcnt exbits index l/lind waitdx blkpos\n let lc = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0;\n for (; i + 2 < s; ++i) {\n // hash value\n const hv = hsh(i);\n // index mod 32768 previous index mod\n let imod = i & 32767, pimod = head[hv];\n prev[imod] = pimod;\n head[hv] = imod;\n // We always should modify head and prev, but only add symbols if\n // this data is not yet processed (\"wait\" for wait index)\n if (wi <= i) {\n // bytes remaining\n const rem = s - i;\n if ((lc > 7000 || li > 24576) && (rem > 423 || !lst)) {\n pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);\n li = lc = eb = 0, bs = i;\n for (let j = 0; j < 286; ++j) lf[j] = 0;\n for (let j = 0; j < 30; ++j) df[j] = 0;\n }\n // len dist chain\n let l = 2, d = 0, ch = c, dif = imod - pimod & 32767;\n if (rem > 2 && hv == hsh(i - dif)) {\n const maxn = Math.min(n, rem) - 1;\n const maxd = Math.min(32767, i);\n // max possible length\n // not capped at dif because decompressors implement \"rolling\" index population\n const ml = Math.min(258, rem);\n while (dif <= maxd && --ch && imod != pimod) {\n if (dat[i + l] == dat[i + l - dif]) {\n let nl = 0;\n for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl);\n if (nl > l) {\n l = nl, d = dif;\n // break out early when we reach \"nice\" (we are satisfied enough)\n if (nl > maxn) break;\n // now, find the rarest 2-byte sequence within this\n // length of literals and search for that instead.\n // Much faster than just using the start\n const mmd = Math.min(dif, nl - 2);\n let md = 0;\n for (let j = 0; j < mmd; ++j) {\n const ti = i - dif + j & 32767;\n const pti = prev[ti];\n const cd = ti - pti & 32767;\n if (cd > md) md = cd, pimod = ti;\n }\n }\n }\n // check the previous match\n imod = pimod, pimod = prev[imod];\n dif += imod - pimod & 32767;\n }\n }\n // d will be nonzero only when a match was found\n if (d) {\n // store both dist and len data in one int32\n // Make sure this is recognized as a len/dist with 28th bit (2^28)\n syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d];\n const lin = revfl[l] & 31, din = revfd[d] & 31;\n eb += fleb[lin] + fdeb[din];\n ++lf[257 + lin];\n ++df[din];\n wi = i + l;\n ++lc;\n } else {\n syms[li++] = dat[i];\n ++lf[dat[i]];\n }\n }\n }\n for (i = Math.max(i, wi); i < s; ++i) {\n syms[li++] = dat[i];\n ++lf[dat[i]];\n }\n pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);\n if (!lst) {\n st.r = (pos & 7) | w[(pos / 8) | 0] << 3;\n // shft(pos) now 1 less if pos & 7 != 0\n pos -= 7;\n st.h = head, st.p = prev, st.i = i, st.w = wi;\n }\n } else {\n for (let i = st.w || 0; i < s + lst; i += 65535) {\n // end\n let e = i + 65535;\n if (e >= s) {\n // write final block\n w[(pos / 8) | 0] = lst;\n e = s;\n }\n pos = wfblk(w, pos + 1, dat.subarray(i, e));\n }\n st.i = s;\n }\n return slc(o, 0, pre + shft(pos) + post);\n}\n\n// crc check\ntype CRCV = {\n p(d: Uint8Array): void;\n d(): number;\n};\n\n// CRC32 table\nconst crct = /*#__PURE__*/ (() => {\n const t = new Int32Array(256);\n for (let i = 0; i < 256; ++i) {\n let c = i, k = 9;\n while (--k) c = ((c & 1) && -306674912) ^ (c >>> 1);\n t[i] = c;\n }\n return t;\n})();\n\n// CRC32\nconst crc = (): CRCV => {\n let c = -1;\n return {\n p(d) {\n // closures have awful performance\n let cr = c;\n for (let i = 0; i < d.length; ++i) cr = crct[(cr & 255) ^ d[i]] ^ (cr >>> 8);\n c = cr;\n },\n d() { return ~c; }\n }\n}\n\n// Adler32\nconst adler = (): CRCV => {\n let a = 1, b = 0;\n return {\n p(d) {\n // closures have awful performance\n let n = a, m = b;\n const l = d.length | 0;\n for (let i = 0; i != l;) {\n const e = Math.min(i + 2655, l);\n for (; i < e; ++i) m += n += d[i];\n n = (n & 65535) + 15 * (n >> 16), m = (m & 65535) + 15 * (m >> 16);\n }\n a = n, b = m;\n },\n d() {\n a %= 65521, b %= 65521;\n return (a & 255) << 24 | (a & 0xFF00) << 8 | (b & 255) << 8 | (b >> 8);\n }\n }\n}\n\n/**\n * Options for decompressing a DEFLATE stream\n */\nexport interface InflateStreamOptions {\n /**\n * The dictionary used to compress the original data. If no dictionary was used during compression, this option has no effect.\n * \n * Supplying the wrong dictionary during decompression usually yields corrupt output or causes an invalid distance error.\n */\n dictionary?: Uint8Array;\n}\n\n/**\n * Options for decompressing DEFLATE data\n */\nexport interface InflateOptions extends InflateStreamOptions {\n /**\n * The buffer into which to write the decompressed data. Saves memory if you know the decompressed size in advance.\n * \n * Note that if the decompression result is larger than the size of this buffer, it will be truncated to fit.\n */\n out?: Uint8Array;\n}\n\n/**\n * Options for decompressing a GZIP stream\n */\nexport interface GunzipStreamOptions extends InflateStreamOptions {}\n\n/**\n * Options for decompressing GZIP data\n */\nexport interface GunzipOptions extends InflateStreamOptions {\n /**\n * The buffer into which to write the decompressed data. GZIP already encodes the output size, so providing this doesn't save memory.\n * \n * Note that if the decompression result is larger than the size of this buffer, it will be truncated to fit.\n */\n out?: Uint8Array;\n}\n\n/**\n * Options for decompressing a Zlib stream\n */\nexport interface UnzlibStreamOptions extends InflateStreamOptions {}\n\n/**\n * Options for decompressing Zlib data\n */\nexport interface UnzlibOptions extends InflateOptions {}\n\n/**\n * Options for compressing data into a DEFLATE format\n */\nexport interface DeflateOptions {\n /**\n * The level of compression to use, ranging from 0-9.\n * \n * 0 will store the data without compression.\n * 1 is fastest but compresses the worst, 9 is slowest but compresses the best.\n * The default level is 6.\n * \n * Typically, binary data benefits much more from higher values than text data.\n * In both cases, higher values usually take disproportionately longer than the reduction in final size that results.\n * \n * For example, a 1 MB text file could:\n * - become 1.01 MB with level 0 in 1ms\n * - become 400 kB with level 1 in 10ms\n * - become 320 kB with level 9 in 100ms\n */\n level?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;\n /**\n * The memory level to use, ranging from 0-12. Increasing this increases speed and compression ratio at the cost of memory.\n * \n * Note that this is exponential: while level 0 uses 4 kB, level 4 uses 64 kB, level 8 uses 1 MB, and level 12 uses 16 MB.\n * It is recommended not to lower the value below 4, since that tends to hurt performance.\n * In addition, values above 8 tend to help very little on most data and can even hurt performance.\n * \n * The default value is automatically determined based on the size of the input data.\n */\n mem?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;\n /**\n * A buffer containing common byte sequences in the input data that can be used to significantly improve compression ratios.\n * \n * Dictionaries should be 32kB or smaller and include strings or byte sequences likely to appear in the input.\n * The decompressor must supply the same dictionary as the compressor to extract the original data.\n * \n * Dictionaries only improve aggregate compression ratio when reused across multiple small inputs. They should typically not be used otherwise.\n * \n * Avoid using dictionaries with GZIP and ZIP to maximize software compatibility.\n */\n dictionary?: Uint8Array;\n};\n\n/**\n * Options for compressing data into a GZIP format\n */\nexport interface GzipOptions extends DeflateOptions {\n /**\n * When the file was last modified. Defaults to the current time.\n * Set this to 0 to avoid revealing a modification date entirely.\n */\n mtime?: Date | string | number;\n /**\n * The filename of the data. If the `gunzip` command is used to decompress the data, it will output a file\n * with this name instead of the name of the compressed file.\n */\n filename?: string;\n}\n\n/**\n * Options for compressing data into a Zlib format\n */\nexport interface ZlibOptions extends DeflateOptions {}\n\n/**\n * Handler for data (de)compression streams\n * @param data The data output from the stream processor\n * @param final Whether this is the final block\n */\nexport type FlateStreamHandler = (data: Uint8Array, final: boolean) => void;\n\n/**\n * Handler for asynchronous data (de)compression streams\n * @param err Any error that occurred\n * @param data The data output from the stream processor\n * @param final Whether this is the final block\n */\nexport type AsyncFlateStreamHandler = (err: FlateError | null, data: Uint8Array, final: boolean) => void;\n\n/**\n * Handler for the asynchronous completion of (de)compression for a data chunk\n * @param size The number of bytes that were processed. This is measured in terms of the input\n * (i.e. compressed bytes for decompression, uncompressed bytes for compression.)\n */\nexport type AsyncFlateDrainHandler = (size: number) => void;\n\n/**\n * Callback for asynchronous (de)compression methods\n * @param err Any error that occurred\n * @param data The resulting data. Only present if `err` is null\n */\nexport type FlateCallback = (err: FlateError | null, data: Uint8Array) => void;\n\n// async callback-based compression\ninterface AsyncOptions {\n /**\n * Whether or not to \"consume\" the source data. This will make the typed array/buffer you pass in\n * unusable but will increase performance and reduce memory usage.\n */\n consume?: boolean;\n}\n\n/**\n * Options for compressing data asynchronously into a DEFLATE format\n */\nexport interface AsyncDeflateOptions extends DeflateOptions, AsyncOptions {}\n\n/**\n * Options for decompressing DEFLATE data asynchronously\n */\nexport interface AsyncInflateOptions extends AsyncOptions, InflateStreamOptions {\n /**\n * The original size of the data. Currently, the asynchronous API disallows\n * writing into a buffer you provide; the best you can do is provide the\n * size in bytes and be given back a new typed array.\n */\n size?: number;\n}\n\n/**\n * Options for compressing data asynchronously into a GZIP format\n */\nexport interface AsyncGzipOptions extends GzipOptions, AsyncOptions {}\n\n/**\n * Options for decompressing GZIP data asynchronously\n */\nexport interface AsyncGunzipOptions extends AsyncOptions, InflateStreamOptions {}\n\n/**\n * Options for compressing data asynchronously into a Zlib format\n */\nexport interface AsyncZlibOptions extends ZlibOptions, AsyncOptions {}\n\n/**\n * Options for decompressing Zlib data asynchronously\n */\nexport interface AsyncUnzlibOptions extends AsyncInflateOptions {}\n\n/**\n * A terminable compression/decompression process\n */\nexport interface AsyncTerminable {\n /**\n * Terminates the worker thread immediately. The callback will not be called.\n */\n (): void;\n}\n\n// deflate with opts\nconst dopt = (dat: Uint8Array, opt: DeflateOptions, pre: number, post: number, st?: DeflateState) => {\n if (!st) {\n st = { l: 1 };\n if (opt.dictionary) {\n const dict = opt.dictionary.subarray(-32768);\n const newDat = new u8(dict.length + dat.length);\n newDat.set(dict);\n newDat.set(dat, dict.length);\n dat = newDat;\n st.w = dict.length;\n }\n }\n return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? (st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20) : (12 + opt.mem), pre, post, st);\n}\n \n\n// Walmart object spread\nconst mrg = <A, B>(a: A, b: B) => {\n const o = {} as Record<string, unknown>;\n for (const k in a) o[k] = a[k];\n for (const k in b) o[k] = b[k];\n return o as A & B;\n}\n\n// worker clone\n\n// This is possibly the craziest part of the entire codebase, despite how simple it may seem.\n// The only parameter to this function is a closure that returns an array of variables outside of the function scope.\n// We're going to try to figure out the variable names used in the closure as strings because that is crucial for workerization.\n// We will return an object mapping of true variable name to value (basically, the current scope as a JS object).\n// The reason we can't just use the original variable names is minifiers mangling the toplevel scope.\n\n// This took me three weeks to figure out how to do.\nconst wcln = (fn: () => unknown[], fnStr: string, td: Record<string, unknown>) => {\n const dt = fn();\n const st = fn.toString();\n const ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/\\s+/g, '').split(',');\n for (let i = 0; i < dt.length; ++i) {\n let v = dt[i], k = ks[i];\n if (typeof v == 'function') {\n fnStr += ';' + k + '=';\n const st = v.toString();\n if (v.prototype) {\n // for global objects\n if (st.indexOf('[native code]') != -1) {\n const spInd = st.indexOf(' ', 8) + 1;\n fnStr += st.slice(spInd, st.indexOf('(', spInd));\n } else {\n fnStr += st;\n for (const t in v.prototype) fnStr += ';' + k + '.prototype.' + t + '=' + v.prototype[t].toString();\n }\n } else fnStr += st;\n } else td[k] = v;\n }\n return fnStr;\n}\n\ntype CachedWorker = {\n // code\n c: string;\n // extra\n e: Record<string, unknown>\n};\n\nconst ch: CachedWorker[] = [];\n// clone bufs\nconst cbfs = (v: Record<string, unknown>) => {\n const tl: ArrayBuffer[] = [];\n for (const k in v) {\n if ((v[k] as Uint8Array).buffer) {\n tl.push((v[k] = new (v[k].constructor as typeof u8)(v[k] as Uint8Array)).buffer);\n }\n }\n return tl;\n}\n\n// use a worker to execute code\nconst wrkr = <T, R>(fns: (() => unknown[])[], init: (ev: MessageEvent<T>) => void, id: number, cb: (err: FlateError, msg: R) => void) => {\n if (!ch[id]) {\n let fnStr = '', td: Record<string, unknown> = {}, m = fns.length - 1;\n for (let i = 0; i < m; ++i)\n fnStr = wcln(fns[i], fnStr, td);\n ch[id] = { c: wcln(fns[m], fnStr, td), e: td };\n }\n const td = mrg({}, ch[id].e);\n return wk(ch[id].c + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb);\n}\n\n// base async inflate fn\nconst bInflt = () => [u8, u16, i32, fleb, fdeb, clim, fl, fd, flrm, fdrm, rev, ec, hMap, max, bits, bits16, shft, slc, err, inflt, inflateSync, pbf, gopt];\nconst bDflt = () => [u8, u16, i32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf];\n\n// gzip extra\nconst gze = () => [gzh, gzhl, wbytes, crc, crct];\n// gunzip extra\nconst guze = () => [gzs, gzl];\n// zlib extra\nconst zle = () => [zlh, wbytes, adler];\n// unzlib extra\nconst zule = () => [zls];\n\n// post buf\nconst pbf = (msg: Uint8Array) => (postMessage as Worker['postMessage'])(msg, [msg.buffer]);\n\n// get opts\nconst gopt = (o?: AsyncInflateOptions) => o && {\n out: o.size && new u8(o.size),\n dictionary: o.dictionary\n};\n\n// async helper\nconst cbify = <T extends AsyncOptions>(dat: Uint8Array, opts: T, fns: (() => unknown[])[], init: (ev: MessageEvent<[Uint8Array, T]>) => void, id: number, cb: FlateCallback) => {\n const w = wrkr<[Uint8Array, T], Uint8Array>(\n fns,\n init,\n id,\n (err, dat) => {\n w.terminate();\n cb(err, dat);\n }\n );\n w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []);\n return () => { w.terminate(); };\n}\n\ntype CmpDecmpStrm = Inflate | Deflate | Gzip | Gunzip | Zlib | Unzlib;\n\n// auto stream\nconst astrm = (strm: CmpDecmpStrm) => {\n strm.ondata = (dat, final) => (postMessage as Worker['postMessage'])([dat, final], [dat.buffer]);\n return (ev: MessageEvent<[Uint8Array, boolean] | []>) => {\n if (ev.data.length) {\n strm.push(ev.data[0], ev.data[1]);\n (postMessage as Worker['postMessage'])([ev.data[0].length]);\n } else (strm as Deflate | Gzip | Zlib).flush()\n }\n}\n\ntype Astrm = { ondata: AsyncFlateStreamHandler; push: (d: Uint8Array, f?: boolean) => void; terminate: AsyncTerminable; flush?: () => void; ondrain?: AsyncFlateDrainHandler; queuedSize: number; };\n\n// async stream attach\nconst astrmify = <T>(fns: (() => unknown[])[], strm: Astrm, opts: T | 0, init: (ev: MessageEvent<T>) => void, id: number, flush: 0 | 1, ext?: (msg: unknown) => unknown) => {\n let t: boolean;\n const w = wrkr<T, [number] | [Uint8Array, boolean]>(\n fns,\n init,\n id,\n (err, dat) => {\n if (err) w.terminate(), strm.ondata.call(strm, err);\n else if (!Array.isArray(dat)) ext(dat);\n else if (dat.length == 1) {\n strm.queuedSize -= dat[0];\n if (strm.ondrain) strm.ondrain(dat[0]);\n } else {\n if (dat[1]) w.terminate();\n strm.ondata.call(strm, err, dat[0], dat[1]);\n }\n }\n )\n w.postMessage(opts);\n strm.queuedSize = 0;\n strm.push = (d, f) => {\n if (!strm.ondata) err(5);\n if (t) strm.ondata(err(4, 0, 1), null, !!f);\n strm.queuedSize += d.length;\n w.postMessage([d, t = f], [d.buffer]);\n };\n strm.terminate = () => { w.terminate(); };\n if (flush) {\n strm.flush = () => { w.postMessage([]); };\n }\n}\n\n// read 2 bytes\nconst b2 = (d: Uint8Array, b: number) => d[b] | (d[b + 1] << 8);\n\n// read 4 bytes\nconst b4 = (d: Uint8Array, b: number) => (d[b] | (d[b + 1] << 8) | (d[b + 2] << 16) | (d[b + 3] << 24)) >>> 0;\n\nconst b8 = (d: Uint8Array, b: number) => b4(d, b) + (b4(d, b + 4) * 4294967296);\n\n// write bytes\nconst wbytes = (d: Uint8Array, b: number, v: number) => {\n for (; v; ++b) d[b] = v, v >>>= 8;\n}\n\n// gzip header\nconst gzh = (c: Uint8Array, o: GzipOptions) => {\n const fn = o.filename;\n c[0] = 31, c[1] = 139, c[2] = 8, c[8] = o.level < 2 ? 4 : o.level == 9 ? 2 : 0, c[9] = 3; // assume Unix\n if (o.mtime != 0) wbytes(c, 4, Math.floor((new Date(o.mtime as (string | number) || Date.now()) as unknown as number) / 1000));\n if (fn) {\n c[3] = 8;\n for (let i = 0; i <= fn.length; ++i) c[i + 10] = fn.charCodeAt(i);\n }\n}\n\n// gzip footer: -8 to -4 = CRC, -4 to -0 is length\n\n// gzip start\nconst gzs = (d: Uint8Array) => {\n if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, 'invalid gzip data');\n const flg = d[3];\n let st = 10;\n if (flg & 4) st += (d[10] | d[11] << 8) + 2;\n for (let zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++] as unknown as number);\n return st + (flg & 2);\n}\n\n// gzip length\nconst gzl = (d: Uint8Array) => {\n const l = d.length;\n return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;\n}\n\n// gzip header length\nconst gzhl = (o: GzipOptions) => 10 + (o.filename ? o.filename.length + 1 : 0);\n\n// zlib header\nconst zlh = (c: Uint8Array, o: ZlibOptions) => {\n const lv = o.level, fl = lv == 0 ? 0 : lv < 6 ? 1 : lv == 9 ? 3 : 2;\n c[0] = 120, c[1] = (fl << 6) | (o.dictionary && 32);\n c[1] |= 31 - ((c[0] << 8) | c[1]) % 31;\n if (o.dictionary) {\n const h = adler();\n h.p(o.dictionary);\n wbytes(c, 2, h.d());\n }\n}\n\n// zlib start\nconst zls = (d: Uint8Array, dict?: unknown) => {\n if ((d[0] & 15) != 8 || (d[0] >> 4) > 7 || ((d[0] << 8 | d[1]) % 31)) err(6, 'invalid zlib data');\n if ((d[1] >> 5 & 1) == +!dict) err(6, 'invalid zlib data: ' + (d[1] & 32 ? 'need' : 'unexpected') + ' dictionary');\n return (d[1] >> 3 & 4) + 2;\n}\n\n// stream options and callback\nfunction StrmOpt<T, H>(opts: T, cb?: H): T;\nfunction StrmOpt<T, H>(cb?: H): T;\nfunction StrmOpt<T, H>(opts?: T | H, cb?: H): T {\n if (typeof opts == 'function') cb = opts as H, opts = {} as T;\n this.ondata = cb as H;\n return opts as T;\n}\n\n/**\n * Streaming DEFLATE compression\n */\nexport class Deflate {\n /**\n * Creates a DEFLATE stream\n * @param opts The compression options\n * @param cb The callback to call whenever data is deflated\n */\n constructor(opts: DeflateOptions, cb?: FlateStreamHandler);\n /**\n * Creates a DEFLATE stream\n * @param cb The callback to call whenever data is deflated\n */\n constructor(cb?: FlateStreamHandler);\n constructor(opts?: DeflateOptions | FlateStreamHandler, cb?: FlateStreamHandler) {\n if (typeof opts == 'function') cb = opts as FlateStreamHandler, opts = {};\n this.ondata = cb;\n this.o = (opts as DeflateOptions) || {};\n this.s = { l: 0, i: 32768, w: 32768, z: 32768 };\n // Buffer length must always be 0 mod 32768 for index calculations to be correct when modifying head and prev\n // 98304 = 32768 (lookback) + 65536 (common chunk size)\n this.b = new u8(98304);\n if (this.o.dictionary) {\n const dict = this.o.dictionary.subarray(-32768);\n this.b.set(dict, 32768 - dict.length);\n this.s.i = 32768 - dict.length;\n }\n }\n private b: Uint8Array;\n private s: DeflateState;\n private o: DeflateOptions;\n /**\n * The handler to call whenever data is available\n */\n ondata: FlateStreamHandler;\n\n private p(c: Uint8Array, f: boolean) {\n this.ondata(dopt(c, this.o, 0, 0, this.s), f);\n }\n\n /**\n * Pushes a chunk to be deflated\n * @param chunk The chunk to push\n * @param final Whether this is the last chunk\n */\n push(chunk: Uint8Array, final?: boolean) {\n if (!this.ondata) err(5);\n if (this.s.l) err(4);\n const endLen = chunk.length + this.s.z;\n if (endLen > this.b.length) {\n if (endLen > 2 * this.b.length - 32768) {\n const newBuf = new u8(endLen & -32768);\n newBuf.set(this.b.subarray(0, this.s.z));\n this.b = newBuf;\n }\n\n const split = this.b.length - this.s.z;\n this.b.set(chunk.subarray(0, split), this.s.z);\n this.s.z = this.b.length;\n this.p(this.b, false);\n\n this.b.set(this.b.subarray(-32768));\n this.b.set(chunk.subarray(split), 32768);\n this.s.z = chunk.length - split + 32768;\n this.s.i = 32766, this.s.w = 32768;\n } else {\n this.b.set(chunk, this.s.z);\n this.s.z += chunk.length;\n }\n this.s.l = (final as unknown as number) & 1;\n if (this.s.z > this.s.w + 8191 || final) {\n this.p(this.b, final || false);\n this.s.w = this.s.i, this.s.i -= 2;\n }\n }\n\n /**\n * Flushes buffered uncompressed data. Useful to immediately retrieve the\n * deflated output for small inputs.\n */\n flush() {\n if (!this.ondata) err(5);\n if (this.s.l) err(4);\n this.p(this.b, false);\n this.s.w = this.s.i, this.s.i -= 2;\n }\n}\n\n/**\n * Asynchronous streaming DEFLATE compression\n */\nexport class AsyncDeflate {\n /**\n * The handler to call whenever data is available\n */\n ondata: AsyncFlateStreamHandler;\n\n /**\n * The handler to call whenever buffered source data is processed (i.e. `queuedSize` updates)\n */\n ondrain?: AsyncFlateDrainHandler;\n\n /**\n * The number of uncompressed bytes buffered in the stream\n */\n queuedSize: number;\n\n /**\n * Creates an asynchronous DEFLATE stream\n * @param opts The compression options\n * @param cb The callback to call whenever data is deflated\n */\n constructor(opts: DeflateOptions, cb?: AsyncFlateStreamHandler);\n /**\n * Creates an asynchronous DEFLATE stream\n * @param cb The callback to call whenever data is deflated\n */\n constructor(cb?: AsyncFlateStreamHandler);\n constructor(opts?: DeflateOptions | AsyncFlateStreamHandler, cb?: AsyncFlateStreamHandler) {\n astrmify([\n bDflt,\n () => [astrm, Deflate]\n ], this as unknown as Astrm, StrmOpt.call(this, opts, cb), ev => {\n const strm = new Deflate(ev.data);\n onmessage = astrm(strm);\n }, 6, 1);\n }\n\n /**\n * Pushes a chunk to be deflated\n * @param chunk The chunk to push\n * @param final Whether this is the last chunk\n */\n // @ts-ignore\n push(chunk: Uint8Array, final?: boolean): void;\n\n /**\n * Flushes buffered uncompressed data. Useful to immediately retrieve the\n * deflated output for small inputs.\n */\n // @ts-ignore\n flush(): void;\n \n /**\n * A method to terminate the stream's internal worker. Subsequent calls to\n * push() will silently fail.\n */\n terminate: AsyncTerminable;\n}\n\n/**\n * Asynchronously compresses data with DEFLATE without any wrapper\n * @param data The data to compress\n * @param opts The compression options\n * @param cb The function to be called upon compression completion\n * @returns A function that can be used to immediately terminate the compression\n */\nexport function deflate(data: Uint8Array, opts: AsyncDeflateOptions, cb: FlateCallback): AsyncTerminable;\n/**\n * Asynchronously compresses data with DEFLATE without any wrapper\n * @param data The data to compress\n * @param cb The function to be called upon compression completion\n */\nexport function deflate(data: Uint8Array, cb: FlateCallback): AsyncTerminable;\nexport function deflate(data: Uint8Array, opts: AsyncDeflateOptions | FlateCallback, cb?: FlateCallback) {\n if (!cb) cb = opts as FlateCallback, opts = {};\n if (typeof cb != 'function') err(7);\n return cbify(data, opts as AsyncDeflateOptions, [\n bDflt,\n ], ev => pbf(deflateSync(ev.data[0], ev.data[1])), 0, cb);\n}\n\n/**\n * Compresses data with DEFLATE without any wrapper\n * @param data The data to compress\n * @param opts The compression options\n * @returns The deflated version of the data\n */\nexport function deflateSync(data: Uint8Array, opts?: DeflateOptions) {\n return dopt(data, opts || {}, 0, 0);\n}\n\n/**\n * Streaming DEFLATE decompression\n */\nexport class Inflate {\n private s: InflateState;\n private o: Uint8Array;\n private p: Uint8Array;\n private d: boolean;\n /**\n * The handler to call whenever data is available\n */\n ondata: FlateStreamHandler;\n\n /**\n * Creates a DEFLATE decompression stream\n * @param opts The decompression options\n * @param cb The callback to call whenever data is inflated\n */\n constructor(opts: InflateStreamOptions, cb?: FlateStreamHandler);\n /**\n * Creates a DEFLATE decompression stream\n * @param cb The callback to call whenever data is inflated\n */\n constructor(cb?: FlateStreamHandler);\n constructor(opts?: InflateStreamOptions | FlateStreamHandler, cb?: FlateStreamHandler) {\n // no StrmOpt here to avoid adding to workerizer\n if (typeof opts == 'function') cb = opts as FlateStreamHandler, opts = {};\n this.ondata = cb;\n const dict = opts && (opts as InflateStreamOptions).dictionary && (opts as InflateStreamOptions).dictionary.subarray(-32768);\n this.s = { i: 0, b: dict ? dict.length : 0 };\n this.o = new u8(32768);\n this.p = new u8(0);\n if (dict) this.o.set(dict);\n }\n\n private e(c: Uint8Array) {\n if (!this.ondata) err(5);\n if (this.d) err(4);\n if (!this.p.length) this.p = c;\n else if (c.length) {\n const n = new u8(this.p.length + c.length);\n n.set(this.p), n.set(c, this.p.length), this.p = n;\n } \n }\n\n private c(final: boolean) {\n this.s.i = +(this.d = final || false);\n const bts = this.s.b;\n const dt = inflt(this.p, this.s, this.o);\n this.ondata(slc(dt, bts, this.s.b), this.d);\n this.o = slc(dt, this.s.b - 32768), this.s.b = this.o.length;\n this.p = slc(this.p, (this.s.p / 8) | 0), this.s.p &= 7;\n }\n\n /**\n * Pushes a chunk to be inflated\n * @param chunk The chunk to push\n * @param final Whether this is the final chunk\n */\n push(chunk: Uint8Array, final?: boolean) {\n this.e(chunk), this.c(final);\n }\n}\n\n/**\n * Asynchronous streaming DEFLATE decompression\n */\nexport class AsyncInflate {\n /**\n * The handler to call whenever data is available\n */\n ondata: AsyncFlateStreamHandler;\n\n /**\n * The handler to call whenever buffered source data is processed (i.e. `queuedSize` updates)\n */\n ondrain?: AsyncFlateDrainHandler;\n\n /**\n * The number of compressed bytes buffered in the stream\n */\n queuedSize: number;\n\n /**\n * Creates an asynchronous DEFLATE decompression stream\n * @param opts The decompression options\n * @param cb