@loaders.gl/compression
Version:
Decompression and compression plugins for loaders.gl
1,597 lines (1,589 loc) • 208 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// dist/index.js
var dist_exports = {};
__export(dist_exports, {
BrotliCompression: () => BrotliCompression,
Compression: () => Compression,
CompressionWorker: () => CompressionWorker,
DeflateCompression: () => DeflateCompression,
GZipCompression: () => GZipCompression,
LZ4Compression: () => LZ4Compression,
LZOCompression: () => LZOCompression,
NoCompression: () => NoCompression,
SnappyCompression: () => SnappyCompression,
ZstdCompression: () => ZstdCompression,
compressOnWorker: () => compressOnWorker
});
module.exports = __toCommonJS(dist_exports);
// dist/lib/compression.js
var import_loader_utils = require("@loaders.gl/loader-utils");
var Compression = class {
constructor(options) {
this.compressBatches = this.compressBatches.bind(this);
this.decompressBatches = this.decompressBatches.bind(this);
}
/** Preloads any dynamic libraries. May enable sync functions */
async preload(modules = {}) {
(0, import_loader_utils.registerJSModules)(modules);
return;
}
/** Asynchronously compress data */
async compress(input) {
await this.preload();
return this.compressSync(input);
}
/** Asynchronously decompress data */
async decompress(input, size) {
await this.preload();
return this.decompressSync(input, size);
}
/** Synchronously compress data */
compressSync(input) {
throw new Error(`${this.name}: sync compression not supported`);
}
/** Synchronously compress data */
decompressSync(input, size) {
throw new Error(`${this.name}: sync decompression not supported`);
}
/** Compress batches */
async *compressBatches(asyncIterator) {
const input = await this.concatenate(asyncIterator);
yield this.compress(input);
}
/** Decompress batches */
async *decompressBatches(asyncIterator) {
const input = await this.concatenate(asyncIterator);
yield this.decompress(input);
}
// HELPERS
concatenate(asyncIterator) {
return (0, import_loader_utils.concatenateArrayBuffersAsync)(asyncIterator);
}
improveError(error) {
if (!error.message.includes(this.name)) {
error.message = `${this.name} ${error.message}`;
}
return error;
}
};
// dist/lib/no-compression.js
var NoCompression = class extends Compression {
name = "uncompressed";
extensions = [];
contentEncodings = [];
isSupported = true;
options;
constructor(options) {
super(options);
this.options = options || {};
}
compressSync(input) {
return input;
}
decompressSync(input) {
return input;
}
async *compressBatches(asyncIterator) {
return yield* asyncIterator;
}
async *decompressBatches(asyncIterator) {
return yield* asyncIterator;
}
};
// dist/lib/deflate-compression.js
var import_loader_utils2 = require("@loaders.gl/loader-utils");
var import_pako = __toESM(require("pako"), 1);
var import_zlib = __toESM(require("zlib"), 1);
var DeflateCompression = class extends Compression {
name = "deflate";
extensions = [];
contentEncodings = ["deflate"];
isSupported = true;
options;
_chunks = [];
constructor(options = {}) {
super(options);
this.options = options;
}
async compress(input) {
var _a, _b;
if (!import_loader_utils2.isBrowser && ((_a = this.options.deflate) == null ? void 0 : _a.useZlib)) {
const buffer = ((_b = this.options.deflate) == null ? void 0 : _b.gzip) ? await (0, import_loader_utils2.promisify1)(import_zlib.default.gzip)(input) : await (0, import_loader_utils2.promisify1)(import_zlib.default.deflate)(input);
return (0, import_loader_utils2.toArrayBuffer)(buffer);
}
return this.compressSync(input);
}
async decompress(input) {
var _a, _b;
if (!import_loader_utils2.isBrowser && ((_a = this.options.deflate) == null ? void 0 : _a.useZlib)) {
const buffer = ((_b = this.options.deflate) == null ? void 0 : _b.gzip) ? await (0, import_loader_utils2.promisify1)(import_zlib.default.gunzip)(input) : await (0, import_loader_utils2.promisify1)(import_zlib.default.inflate)(input);
return (0, import_loader_utils2.toArrayBuffer)(buffer);
}
return this.decompressSync(input);
}
compressSync(input) {
var _a, _b, _c, _d;
if (!import_loader_utils2.isBrowser && ((_a = this.options.deflate) == null ? void 0 : _a.useZlib)) {
const buffer = ((_b = this.options.deflate) == null ? void 0 : _b.gzip) ? import_zlib.default.gzipSync(input) : import_zlib.default.deflateSync(input);
return (0, import_loader_utils2.toArrayBuffer)(buffer);
}
const pakoOptions = ((_c = this.options) == null ? void 0 : _c.deflate) || {};
const inputArray = new Uint8Array(input);
const deflate = ((_d = this.options) == null ? void 0 : _d.raw) ? import_pako.default.deflateRaw : import_pako.default.deflate;
return deflate(inputArray, pakoOptions).buffer;
}
decompressSync(input) {
var _a, _b, _c, _d;
if (!import_loader_utils2.isBrowser && ((_a = this.options.deflate) == null ? void 0 : _a.useZlib)) {
const buffer = ((_b = this.options.deflate) == null ? void 0 : _b.gzip) ? import_zlib.default.gunzipSync(input) : import_zlib.default.inflateSync(input);
return (0, import_loader_utils2.toArrayBuffer)(buffer);
}
const pakoOptions = ((_c = this.options) == null ? void 0 : _c.deflate) || {};
const inputArray = new Uint8Array(input);
const inflate = ((_d = this.options) == null ? void 0 : _d.raw) ? import_pako.default.inflateRaw : import_pako.default.inflate;
return inflate(inputArray, pakoOptions).buffer;
}
async *compressBatches(asyncIterator) {
var _a;
const pakoOptions = ((_a = this.options) == null ? void 0 : _a.deflate) || {};
const pakoProcessor = new import_pako.default.Deflate(pakoOptions);
yield* this.transformBatches(pakoProcessor, asyncIterator);
}
async *decompressBatches(asyncIterator) {
var _a;
const pakoOptions = ((_a = this.options) == null ? void 0 : _a.deflate) || {};
const pakoProcessor = new import_pako.default.Inflate(pakoOptions);
yield* this.transformBatches(pakoProcessor, asyncIterator);
}
async *transformBatches(pakoProcessor, asyncIterator) {
pakoProcessor.onData = this._onData.bind(this);
pakoProcessor.onEnd = this._onEnd.bind(this);
for await (const chunk of asyncIterator) {
const uint8Array = new Uint8Array(chunk);
const ok2 = pakoProcessor.push(uint8Array, false);
if (!ok2) {
throw new Error(`${this._getError()}write`);
}
const chunks2 = this._getChunks();
yield* chunks2;
}
const emptyChunk = new Uint8Array(0);
const ok = pakoProcessor.push(emptyChunk, true);
if (!ok) {
}
const chunks = this._getChunks();
yield* chunks;
}
_onData(chunk) {
this._chunks.push(chunk);
}
_onEnd(status) {
if (status !== 0) {
throw new Error(this._getError(status) + this._chunks.length);
}
}
_getChunks() {
const chunks = this._chunks;
this._chunks = [];
return chunks;
}
// TODO - For some reason we don't get the error message from pako in _onEnd?
_getError(code = 0) {
const MESSAGES = {
/* Z_NEED_DICT 2 */
2: "need dictionary",
/* Z_STREAM_END 1 */
1: "stream end",
/* Z_OK 0 */
0: "",
/* Z_ERRNO (-1) */
"-1": "file error",
/* Z_STREAM_ERROR (-2) */
"-2": "stream error",
/* Z_DATA_ERROR (-3) */
"-3": "data error",
/* Z_MEM_ERROR (-4) */
"-4": "insufficient memory",
/* Z_BUF_ERROR (-5) */
"-5": "buffer error",
/* Z_VERSION_ERROR (-6) */
"-6": "incompatible version"
};
return `${this.name}: ${MESSAGES[code]}`;
}
};
// dist/lib/gzip-compression.js
var GZipCompression = class extends DeflateCompression {
name = "gzip";
extensions = ["gz", "gzip"];
contentEncodings = ["gzip", "x-gzip"];
isSupported = true;
constructor(options) {
super({ ...options, deflate: { ...options == null ? void 0 : options.gzip, gzip: true } });
}
};
// dist/lib/brotli-compression.js
var import_loader_utils3 = require("@loaders.gl/loader-utils");
// dist/brotli/decode.js
var makeBrotliDecode = () => {
function InputStream(bytes) {
this.data = bytes;
this.offset = 0;
}
let MAX_HUFFMAN_TABLE_SIZE = Int32Array.from([
256,
402,
436,
468,
500,
534,
566,
598,
630,
662,
694,
726,
758,
790,
822,
854,
886,
920,
952,
984,
1016,
1048,
1080
]);
let CODE_LENGTH_CODE_ORDER = Int32Array.from([
1,
2,
3,
4,
0,
5,
17,
6,
16,
7,
8,
9,
10,
11,
12,
13,
14,
15
]);
let DISTANCE_SHORT_CODE_INDEX_OFFSET = Int32Array.from([
0,
3,
2,
1,
0,
0,
0,
0,
0,
0,
3,
3,
3,
3,
3,
3
]);
let DISTANCE_SHORT_CODE_VALUE_OFFSET = Int32Array.from([
0,
0,
0,
0,
-1,
1,
-2,
2,
-3,
3,
-1,
1,
-2,
2,
-3,
3
]);
let FIXED_TABLE = Int32Array.from([
131072,
131076,
131075,
196610,
131072,
131076,
131075,
262145,
131072,
131076,
131075,
196610,
131072,
131076,
131075,
262149
]);
let BLOCK_LENGTH_OFFSET = Int32Array.from([
1,
5,
9,
13,
17,
25,
33,
41,
49,
65,
81,
97,
113,
145,
177,
209,
241,
305,
369,
497,
753,
1265,
2289,
4337,
8433,
16625
]);
let BLOCK_LENGTH_N_BITS = Int32Array.from([
2,
2,
2,
2,
3,
3,
3,
3,
4,
4,
4,
4,
5,
5,
5,
5,
6,
6,
7,
8,
9,
10,
11,
12,
13,
24
]);
let INSERT_LENGTH_N_BITS = Int16Array.from([
0,
0,
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
7,
8,
9,
10,
12,
14,
24
]);
let COPY_LENGTH_N_BITS = Int16Array.from([
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
2,
2,
3,
3,
4,
4,
5,
5,
6,
7,
8,
9,
10,
24
]);
let CMD_LOOKUP = new Int16Array(2816);
{
unpackCommandLookupTable(CMD_LOOKUP);
}
function log2floor(i) {
let result = -1;
let step = 16;
while (step > 0) {
if (i >>> step != 0) {
result += step;
i = i >>> step;
}
step = step >> 1;
}
return result + i;
}
function calculateDistanceAlphabetSize(npostfix, ndirect, maxndistbits) {
return 16 + ndirect + 2 * (maxndistbits << npostfix);
}
function calculateDistanceAlphabetLimit(maxDistance, npostfix, ndirect) {
if (maxDistance < ndirect + (2 << npostfix)) {
throw "maxDistance is too small";
}
let offset = (maxDistance - ndirect >> npostfix) + 4;
let ndistbits = log2floor(offset) - 1;
let group = ndistbits - 1 << 1 | offset >> ndistbits & 1;
return (group - 1 << npostfix) + (1 << npostfix) + ndirect + 16;
}
function unpackCommandLookupTable(cmdLookup) {
let insertLengthOffsets = new Int16Array(24);
let copyLengthOffsets = new Int16Array(24);
copyLengthOffsets[0] = 2;
for (let i = 0; i < 23; ++i) {
insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);
copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);
}
for (let cmdCode = 0; cmdCode < 704; ++cmdCode) {
let rangeIdx = cmdCode >>> 6;
let distanceContextOffset = -4;
if (rangeIdx >= 2) {
rangeIdx -= 2;
distanceContextOffset = 0;
}
let insertCode = (170064 >>> rangeIdx * 2 & 3) << 3 | cmdCode >>> 3 & 7;
let copyCode = (156228 >>> rangeIdx * 2 & 3) << 3 | cmdCode & 7;
let copyLengthOffset = copyLengthOffsets[copyCode];
let distanceContext = distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
let index = cmdCode * 4;
cmdLookup[index + 0] = INSERT_LENGTH_N_BITS[insertCode] | COPY_LENGTH_N_BITS[copyCode] << 8;
cmdLookup[index + 1] = insertLengthOffsets[insertCode];
cmdLookup[index + 2] = copyLengthOffsets[copyCode];
cmdLookup[index + 3] = distanceContext;
}
}
function decodeWindowBits(s) {
let largeWindowEnabled = s.isLargeWindow;
s.isLargeWindow = 0;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
if (readFewBits(s, 1) == 0) {
return 16;
}
let n = readFewBits(s, 3);
if (n != 0) {
return 17 + n;
}
n = readFewBits(s, 3);
if (n != 0) {
if (n == 1) {
if (largeWindowEnabled == 0) {
return -1;
}
s.isLargeWindow = 1;
if (readFewBits(s, 1) == 1) {
return -1;
}
n = readFewBits(s, 6);
if (n < 10 || n > 30) {
return -1;
}
return n;
} else {
return 8 + n;
}
}
return 17;
}
function enableEagerOutput(s) {
if (s.runningState != 1) {
throw "State MUST be freshly initialized";
}
s.isEager = 1;
}
function enableLargeWindow(s) {
if (s.runningState != 1) {
throw "State MUST be freshly initialized";
}
s.isLargeWindow = 1;
}
function attachDictionaryChunk(s, data2) {
if (s.runningState != 1) {
throw "State MUST be freshly initialized";
}
if (s.cdNumChunks == 0) {
s.cdChunks = new Array(16);
s.cdChunkOffsets = new Int32Array(16);
s.cdBlockBits = -1;
}
if (s.cdNumChunks == 15) {
throw "Too many dictionary chunks";
}
s.cdChunks[s.cdNumChunks] = data2;
s.cdNumChunks++;
s.cdTotalSize += data2.length;
s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;
}
function initState(s, input) {
if (s.runningState != 0) {
throw "State MUST be uninitialized";
}
s.blockTrees = new Int32Array(3091);
s.blockTrees[0] = 7;
s.distRbIdx = 3;
let maxDistanceAlphabetLimit = calculateDistanceAlphabetLimit(2147483644, 3, 15 << 3);
s.distExtraBits = new Int8Array(maxDistanceAlphabetLimit);
s.distOffset = new Int32Array(maxDistanceAlphabetLimit);
s.input = input;
initBitReader(s);
s.runningState = 1;
}
function close(s) {
if (s.runningState == 0) {
throw "State MUST be initialized";
}
if (s.runningState == 11) {
return;
}
s.runningState = 11;
if (s.input != null) {
closeInput(s.input);
s.input = null;
}
}
function decodeVarLenUnsignedByte(s) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
if (readFewBits(s, 1) != 0) {
let n = readFewBits(s, 3);
if (n == 0) {
return 1;
} else {
return readFewBits(s, n) + (1 << n);
}
}
return 0;
}
function decodeMetaBlockLength(s) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
s.inputEnd = readFewBits(s, 1);
s.metaBlockLength = 0;
s.isUncompressed = 0;
s.isMetadata = 0;
if (s.inputEnd != 0 && readFewBits(s, 1) != 0) {
return;
}
let sizeNibbles = readFewBits(s, 2) + 4;
if (sizeNibbles == 7) {
s.isMetadata = 1;
if (readFewBits(s, 1) != 0) {
throw "Corrupted reserved bit";
}
let sizeBytes = readFewBits(s, 2);
if (sizeBytes == 0) {
return;
}
for (let i = 0; i < sizeBytes; i++) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let bits = readFewBits(s, 8);
if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
throw "Exuberant nibble";
}
s.metaBlockLength |= bits << i * 8;
}
} else {
for (let i = 0; i < sizeNibbles; i++) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let bits = readFewBits(s, 4);
if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
throw "Exuberant nibble";
}
s.metaBlockLength |= bits << i * 4;
}
}
s.metaBlockLength++;
if (s.inputEnd == 0) {
s.isUncompressed = readFewBits(s, 1);
}
}
function readSymbol(tableGroup, tableIdx, s) {
let offset = tableGroup[tableIdx];
let val = s.accumulator32 >>> s.bitOffset;
offset += val & 255;
let bits = tableGroup[offset] >> 16;
let sym = tableGroup[offset] & 65535;
if (bits <= 8) {
s.bitOffset += bits;
return sym;
}
offset += sym;
let mask = (1 << bits) - 1;
offset += (val & mask) >>> 8;
s.bitOffset += (tableGroup[offset] >> 16) + 8;
return tableGroup[offset] & 65535;
}
function readBlockLength(tableGroup, tableIdx, s) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let code = readSymbol(tableGroup, tableIdx, s);
let n = BLOCK_LENGTH_N_BITS[code];
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
return BLOCK_LENGTH_OFFSET[code] + (n <= 16 ? readFewBits(s, n) : readManyBits(s, n));
}
function moveToFront(v, index) {
let value = v[index];
for (; index > 0; index--) {
v[index] = v[index - 1];
}
v[0] = value;
}
function inverseMoveToFrontTransform(v, vLen) {
let mtf = new Int32Array(256);
for (let i = 0; i < 256; i++) {
mtf[i] = i;
}
for (let i = 0; i < vLen; i++) {
let index = v[i] & 255;
v[i] = mtf[index];
if (index != 0) {
moveToFront(mtf, index);
}
}
}
function readHuffmanCodeLengths(codeLengthCodeLengths, numSymbols, codeLengths, s) {
let symbol = 0;
let prevCodeLen = 8;
let repeat = 0;
let repeatCodeLen = 0;
let space = 32768;
let table = new Int32Array(32 + 1);
let tableIdx = table.length - 1;
buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, 18);
while (symbol < numSymbols && space > 0) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let p = s.accumulator32 >>> s.bitOffset & 31;
s.bitOffset += table[p] >> 16;
let codeLen = table[p] & 65535;
if (codeLen < 16) {
repeat = 0;
codeLengths[symbol++] = codeLen;
if (codeLen != 0) {
prevCodeLen = codeLen;
space -= 32768 >> codeLen;
}
} else {
let extraBits = codeLen - 14;
let newLen = 0;
if (codeLen == 16) {
newLen = prevCodeLen;
}
if (repeatCodeLen != newLen) {
repeat = 0;
repeatCodeLen = newLen;
}
let oldRepeat = repeat;
if (repeat > 0) {
repeat -= 2;
repeat <<= extraBits;
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
repeat += readFewBits(s, extraBits) + 3;
let repeatDelta = repeat - oldRepeat;
if (symbol + repeatDelta > numSymbols) {
throw "symbol + repeatDelta > numSymbols";
}
for (let i = 0; i < repeatDelta; i++) {
codeLengths[symbol++] = repeatCodeLen;
}
if (repeatCodeLen != 0) {
space -= repeatDelta << 15 - repeatCodeLen;
}
}
}
if (space != 0) {
throw "Unused space";
}
codeLengths.fill(0, symbol, numSymbols);
}
function checkDupes(symbols, length) {
for (let i = 0; i < length - 1; ++i) {
for (let j = i + 1; j < length; ++j) {
if (symbols[i] == symbols[j]) {
throw "Duplicate simple Huffman code symbol";
}
}
}
}
function readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {
let codeLengths = new Int32Array(alphabetSizeLimit);
let symbols = new Int32Array(4);
let maxBits = 1 + log2floor(alphabetSizeMax - 1);
let numSymbols = readFewBits(s, 2) + 1;
for (let i = 0; i < numSymbols; i++) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let symbol = readFewBits(s, maxBits);
if (symbol >= alphabetSizeLimit) {
throw "Can't readHuffmanCode";
}
symbols[i] = symbol;
}
checkDupes(symbols, numSymbols);
let histogramId = numSymbols;
if (numSymbols == 4) {
histogramId += readFewBits(s, 1);
}
switch (histogramId) {
case 1:
codeLengths[symbols[0]] = 1;
break;
case 2:
codeLengths[symbols[0]] = 1;
codeLengths[symbols[1]] = 1;
break;
case 3:
codeLengths[symbols[0]] = 1;
codeLengths[symbols[1]] = 2;
codeLengths[symbols[2]] = 2;
break;
case 4:
codeLengths[symbols[0]] = 2;
codeLengths[symbols[1]] = 2;
codeLengths[symbols[2]] = 2;
codeLengths[symbols[3]] = 2;
break;
case 5:
codeLengths[symbols[0]] = 1;
codeLengths[symbols[1]] = 2;
codeLengths[symbols[2]] = 3;
codeLengths[symbols[3]] = 3;
break;
default:
break;
}
return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);
}
function readComplexHuffmanCode(alphabetSizeLimit, skip, tableGroup, tableIdx, s) {
let codeLengths = new Int32Array(alphabetSizeLimit);
let codeLengthCodeLengths = new Int32Array(18);
let space = 32;
let numCodes = 0;
for (let i = skip; i < 18 && space > 0; i++) {
let codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let p = s.accumulator32 >>> s.bitOffset & 15;
s.bitOffset += FIXED_TABLE[p] >> 16;
let v = FIXED_TABLE[p] & 65535;
codeLengthCodeLengths[codeLenIdx] = v;
if (v != 0) {
space -= 32 >> v;
numCodes++;
}
}
if (space != 0 && numCodes != 1) {
throw "Corrupted Huffman code histogram";
}
readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);
return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);
}
function readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let simpleCodeOrSkip = readFewBits(s, 2);
if (simpleCodeOrSkip == 1) {
return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
} else {
return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);
}
}
function decodeContextMap(contextMapSize, contextMap, s) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
let numTrees = decodeVarLenUnsignedByte(s) + 1;
if (numTrees == 1) {
contextMap.fill(0, 0, contextMapSize);
return numTrees;
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let useRleForZeros = readFewBits(s, 1);
let maxRunLengthPrefix = 0;
if (useRleForZeros != 0) {
maxRunLengthPrefix = readFewBits(s, 4) + 1;
}
let alphabetSize = numTrees + maxRunLengthPrefix;
let tableSize = MAX_HUFFMAN_TABLE_SIZE[alphabetSize + 31 >> 5];
let table = new Int32Array(tableSize + 1);
let tableIdx = table.length - 1;
readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
for (let i = 0; i < contextMapSize; ) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let code = readSymbol(table, tableIdx, s);
if (code == 0) {
contextMap[i] = 0;
i++;
} else if (code <= maxRunLengthPrefix) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let reps = (1 << code) + readFewBits(s, code);
while (reps != 0) {
if (i >= contextMapSize) {
throw "Corrupted context map";
}
contextMap[i] = 0;
i++;
reps--;
}
} else {
contextMap[i] = code - maxRunLengthPrefix;
i++;
}
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
if (readFewBits(s, 1) == 1) {
inverseMoveToFrontTransform(contextMap, contextMapSize);
}
return numTrees;
}
function decodeBlockTypeAndLength(s, treeType, numBlockTypes) {
let ringBuffers = s.rings;
let offset = 4 + treeType * 2;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let blockType = readSymbol(s.blockTrees, 2 * treeType, s);
let result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
if (blockType == 1) {
blockType = ringBuffers[offset + 1] + 1;
} else if (blockType == 0) {
blockType = ringBuffers[offset];
} else {
blockType -= 2;
}
if (blockType >= numBlockTypes) {
blockType -= numBlockTypes;
}
ringBuffers[offset] = ringBuffers[offset + 1];
ringBuffers[offset + 1] = blockType;
return result;
}
function decodeLiteralBlockSwitch(s) {
s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
let literalBlockType = s.rings[5];
s.contextMapSlice = literalBlockType << 6;
s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 255;
let contextMode = s.contextModes[literalBlockType];
s.contextLookupOffset1 = contextMode << 9;
s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
}
function decodeCommandBlockSwitch(s) {
s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);
s.commandTreeIdx = s.rings[7];
}
function decodeDistanceBlockSwitch(s) {
s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);
s.distContextMapSlice = s.rings[9] << 2;
}
function maybeReallocateRingBuffer(s) {
let newSize = s.maxRingBufferSize;
if (newSize > s.expectedTotalSize) {
let minimalNewSize = s.expectedTotalSize;
while (newSize >> 1 > minimalNewSize) {
newSize >>= 1;
}
if (s.inputEnd == 0 && newSize < 16384 && s.maxRingBufferSize >= 16384) {
newSize = 16384;
}
}
if (newSize <= s.ringBufferSize) {
return;
}
let ringBufferSizeWithSlack = newSize + 37;
let newBuffer = new Int8Array(ringBufferSizeWithSlack);
if (s.ringBuffer.length != 0) {
newBuffer.set(s.ringBuffer.subarray(0, 0 + s.ringBufferSize), 0);
}
s.ringBuffer = newBuffer;
s.ringBufferSize = newSize;
}
function readNextMetablockHeader(s) {
if (s.inputEnd != 0) {
s.nextRunningState = 10;
s.runningState = 12;
return;
}
s.literalTreeGroup = new Int32Array(0);
s.commandTreeGroup = new Int32Array(0);
s.distanceTreeGroup = new Int32Array(0);
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
decodeMetaBlockLength(s);
if (s.metaBlockLength == 0 && s.isMetadata == 0) {
return;
}
if (s.isUncompressed != 0 || s.isMetadata != 0) {
jumpToByteBoundary(s);
s.runningState = s.isMetadata != 0 ? 5 : 6;
} else {
s.runningState = 3;
}
if (s.isMetadata != 0) {
return;
}
s.expectedTotalSize += s.metaBlockLength;
if (s.expectedTotalSize > 1 << 30) {
s.expectedTotalSize = 1 << 30;
}
if (s.ringBufferSize < s.maxRingBufferSize) {
maybeReallocateRingBuffer(s);
}
}
function readMetablockPartition(s, treeType, numBlockTypes) {
let offset = s.blockTrees[2 * treeType];
if (numBlockTypes <= 1) {
s.blockTrees[2 * treeType + 1] = offset;
s.blockTrees[2 * treeType + 2] = offset;
return 1 << 28;
}
let blockTypeAlphabetSize = numBlockTypes + 2;
offset += readHuffmanCode(blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
s.blockTrees[2 * treeType + 1] = offset;
let blockLengthAlphabetSize = 26;
offset += readHuffmanCode(blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
s.blockTrees[2 * treeType + 2] = offset;
return readBlockLength(s.blockTrees, 2 * treeType + 1, s);
}
function calculateDistanceLut(s, alphabetSizeLimit) {
let distExtraBits = s.distExtraBits;
let distOffset = s.distOffset;
let npostfix = s.distancePostfixBits;
let ndirect = s.numDirectDistanceCodes;
let postfix = 1 << npostfix;
let bits = 1;
let half = 0;
let i = 16;
for (let j = 0; j < ndirect; ++j) {
distExtraBits[i] = 0;
distOffset[i] = j + 1;
++i;
}
while (i < alphabetSizeLimit) {
let base = ndirect + ((2 + half << bits) - 4 << npostfix) + 1;
for (let j = 0; j < postfix; ++j) {
distExtraBits[i] = bits;
distOffset[i] = base + j;
++i;
}
bits = bits + half;
half = half ^ 1;
}
}
function readMetablockHuffmanCodesAndContextMaps(s) {
s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;
s.literalBlockLength = readMetablockPartition(s, 0, s.numLiteralBlockTypes);
s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;
s.commandBlockLength = readMetablockPartition(s, 1, s.numCommandBlockTypes);
s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;
s.distanceBlockLength = readMetablockPartition(s, 2, s.numDistanceBlockTypes);
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
s.distancePostfixBits = readFewBits(s, 2);
s.numDirectDistanceCodes = readFewBits(s, 4) << s.distancePostfixBits;
s.contextModes = new Int8Array(s.numLiteralBlockTypes);
for (let i = 0; i < s.numLiteralBlockTypes; ) {
let limit = min(i + 96, s.numLiteralBlockTypes);
for (; i < limit; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
s.contextModes[i] = readFewBits(s, 2);
}
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
}
s.contextMap = new Int8Array(s.numLiteralBlockTypes << 6);
let numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << 6, s.contextMap, s);
s.trivialLiteralContext = 1;
for (let j = 0; j < s.numLiteralBlockTypes << 6; j++) {
if (s.contextMap[j] != j >> 6) {
s.trivialLiteralContext = 0;
break;
}
}
s.distContextMap = new Int8Array(s.numDistanceBlockTypes << 2);
let numDistTrees = decodeContextMap(s.numDistanceBlockTypes << 2, s.distContextMap, s);
s.literalTreeGroup = decodeHuffmanTreeGroup(256, 256, numLiteralTrees, s);
s.commandTreeGroup = decodeHuffmanTreeGroup(704, 704, s.numCommandBlockTypes, s);
let distanceAlphabetSizeMax = calculateDistanceAlphabetSize(s.distancePostfixBits, s.numDirectDistanceCodes, 24);
let distanceAlphabetSizeLimit = distanceAlphabetSizeMax;
if (s.isLargeWindow == 1) {
distanceAlphabetSizeMax = calculateDistanceAlphabetSize(s.distancePostfixBits, s.numDirectDistanceCodes, 62);
distanceAlphabetSizeLimit = calculateDistanceAlphabetLimit(2147483644, s.distancePostfixBits, s.numDirectDistanceCodes);
}
s.distanceTreeGroup = decodeHuffmanTreeGroup(distanceAlphabetSizeMax, distanceAlphabetSizeLimit, numDistTrees, s);
calculateDistanceLut(s, distanceAlphabetSizeLimit);
s.contextMapSlice = 0;
s.distContextMapSlice = 0;
s.contextLookupOffset1 = s.contextModes[0] * 512;
s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
s.literalTreeIdx = 0;
s.commandTreeIdx = 0;
s.rings[4] = 1;
s.rings[5] = 0;
s.rings[6] = 1;
s.rings[7] = 0;
s.rings[8] = 1;
s.rings[9] = 0;
}
function copyUncompressedData(s) {
let ringBuffer = s.ringBuffer;
if (s.metaBlockLength <= 0) {
reload(s);
s.runningState = 2;
return;
}
let chunkLength = min(s.ringBufferSize - s.pos, s.metaBlockLength);
copyRawBytes(s, ringBuffer, s.pos, chunkLength);
s.metaBlockLength -= chunkLength;
s.pos += chunkLength;
if (s.pos == s.ringBufferSize) {
s.nextRunningState = 6;
s.runningState = 12;
return;
}
reload(s);
s.runningState = 2;
}
function writeRingBuffer(s) {
let toWrite = min(s.outputLength - s.outputUsed, s.ringBufferBytesReady - s.ringBufferBytesWritten);
if (toWrite != 0) {
s.output.set(s.ringBuffer.subarray(s.ringBufferBytesWritten, s.ringBufferBytesWritten + toWrite), s.outputOffset + s.outputUsed);
s.outputUsed += toWrite;
s.ringBufferBytesWritten += toWrite;
}
if (s.outputUsed < s.outputLength) {
return 1;
} else {
return 0;
}
}
function decodeHuffmanTreeGroup(alphabetSizeMax, alphabetSizeLimit, n, s) {
let maxTableSize = MAX_HUFFMAN_TABLE_SIZE[alphabetSizeLimit + 31 >> 5];
let group = new Int32Array(n + n * maxTableSize);
let next = n;
for (let i = 0; i < n; ++i) {
group[i] = next;
next += readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, group, i, s);
}
return group;
}
function calculateFence(s) {
let result = s.ringBufferSize;
if (s.isEager != 0) {
result = min(result, s.ringBufferBytesWritten + s.outputLength - s.outputUsed);
}
return result;
}
function doUseDictionary(s, fence) {
if (s.distance > 2147483644) {
throw "Invalid backward reference";
}
let address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
if (address < 0) {
initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
s.runningState = 14;
} else {
let dictionaryData = (
/** @type{!Int8Array} */
data
);
let wordLength = s.copyLength;
if (wordLength > 31) {
throw "Invalid backward reference";
}
let shift = sizeBits[wordLength];
if (shift == 0) {
throw "Invalid backward reference";
}
let offset = offsets[wordLength];
let mask = (1 << shift) - 1;
let wordIdx = address & mask;
let transformIdx = address >>> shift;
offset += wordIdx * wordLength;
let transforms = RFC_TRANSFORMS;
if (transformIdx >= transforms.numTransforms) {
throw "Invalid backward reference";
}
let len = transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData, offset, wordLength, transforms, transformIdx);
s.pos += len;
s.metaBlockLength -= len;
if (s.pos >= fence) {
s.nextRunningState = 4;
s.runningState = 12;
return;
}
s.runningState = 4;
}
}
function initializeCompoundDictionary(s) {
s.cdBlockMap = new Int8Array(256);
let blockBits = 8;
while (s.cdTotalSize - 1 >>> blockBits != 0) {
blockBits++;
}
blockBits -= 8;
s.cdBlockBits = blockBits;
let cursor = 0;
let index = 0;
while (cursor < s.cdTotalSize) {
while (s.cdChunkOffsets[index + 1] < cursor) {
index++;
}
s.cdBlockMap[cursor >>> blockBits] = index;
cursor += 1 << blockBits;
}
}
function initializeCompoundDictionaryCopy(s, address, length) {
if (s.cdBlockBits == -1) {
initializeCompoundDictionary(s);
}
let index = s.cdBlockMap[address >>> s.cdBlockBits];
while (address >= s.cdChunkOffsets[index + 1]) {
index++;
}
if (s.cdTotalSize > address + length) {
throw "Invalid backward reference";
}
s.distRbIdx = s.distRbIdx + 1 & 3;
s.rings[s.distRbIdx] = s.distance;
s.metaBlockLength -= length;
s.cdBrIndex = index;
s.cdBrOffset = address - s.cdChunkOffsets[index];
s.cdBrLength = length;
s.cdBrCopied = 0;
}
function copyFromCompoundDictionary(s, fence) {
let pos = s.pos;
let origPos = pos;
while (s.cdBrLength != s.cdBrCopied) {
let space = fence - pos;
let chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex];
let remChunkLength = chunkLength - s.cdBrOffset;
let length = s.cdBrLength - s.cdBrCopied;
if (length > remChunkLength) {
length = remChunkLength;
}
if (length > space) {
length = space;
}
copyBytes(s.ringBuffer, pos, s.cdChunks[s.cdBrIndex], s.cdBrOffset, s.cdBrOffset + length);
pos += length;
s.cdBrOffset += length;
s.cdBrCopied += length;
if (length == remChunkLength) {
s.cdBrIndex++;
s.cdBrOffset = 0;
}
if (pos >= fence) {
break;
}
}
return pos - origPos;
}
function decompress(s) {
if (s.runningState == 0) {
throw "Can't decompress until initialized";
}
if (s.runningState == 11) {
throw "Can't decompress after close";
}
if (s.runningState == 1) {
let windowBits = decodeWindowBits(s);
if (windowBits == -1) {
throw "Invalid 'windowBits' code";
}
s.maxRingBufferSize = 1 << windowBits;
s.maxBackwardDistance = s.maxRingBufferSize - 16;
s.runningState = 2;
}
let fence = calculateFence(s);
let ringBufferMask = s.ringBufferSize - 1;
let ringBuffer = s.ringBuffer;
while (s.runningState != 10) {
switch (s.runningState) {
case 2:
if (s.metaBlockLength < 0) {
throw "Invalid metablock length";
}
readNextMetablockHeader(s);
fence = calculateFence(s);
ringBufferMask = s.ringBufferSize - 1;
ringBuffer = s.ringBuffer;
continue;
case 3:
readMetablockHuffmanCodesAndContextMaps(s);
s.runningState = 4;
case 4:
if (s.metaBlockLength <= 0) {
s.runningState = 2;
continue;
}
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.commandBlockLength == 0) {
decodeCommandBlockSwitch(s);
}
s.commandBlockLength--;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
let insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
let insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
let copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
s.distanceCode = CMD_LOOKUP[cmdCode + 3];
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let insertLengthExtraBits = insertAndCopyExtraBits & 255;
s.insertLength = insertLengthOffset + (insertLengthExtraBits <= 16 ? readFewBits(s, insertLengthExtraBits) : readManyBits(s, insertLengthExtraBits));
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let copyLengthExtraBits = insertAndCopyExtraBits >> 8;
s.copyLength = copyLengthOffset + (copyLengthExtraBits <= 16 ? readFewBits(s, copyLengthExtraBits) : readManyBits(s, copyLengthExtraBits));
s.j = 0;
s.runningState = 7;
case 7:
if (s.trivialLiteralContext != 0) {
while (s.j < s.insertLength) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.literalBlockLength == 0) {
decodeLiteralBlockSwitch(s);
}
s.literalBlockLength--;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
ringBuffer[s.pos] = readSymbol(s.literalTreeGroup, s.literalTreeIdx, s);
s.pos++;
s.j++;
if (s.pos >= fence) {
s.nextRunningState = 7;
s.runningState = 12;
break;
}
}
} else {
let prevByte1 = ringBuffer[s.pos - 1 & ringBufferMask] & 255;
let prevByte2 = ringBuffer[s.pos - 2 & ringBufferMask] & 255;
while (s.j < s.insertLength) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.literalBlockLength == 0) {
decodeLiteralBlockSwitch(s);
}
let literalContext = LOOKUP[s.contextLookupOffset1 + prevByte1] | LOOKUP[s.contextLookupOffset2 + prevByte2];
let literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 255;
s.literalBlockLength--;
prevByte2 = prevByte1;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
prevByte1 = readSymbol(s.literalTreeGroup, literalTreeIdx, s);
ringBuffer[s.pos] = prevByte1;
s.pos++;
s.j++;
if (s.pos >= fence) {
s.nextRunningState = 7;
s.runningState = 12;
break;
}
}
}
if (s.runningState != 7) {
continue;
}
s.metaBlockLength -= s.insertLength;
if (s.metaBlockLength <= 0) {
s.runningState = 4;
continue;
}
let distanceCode = s.distanceCode;
if (distanceCode < 0) {
s.distance = s.rings[s.distRbIdx];
} else {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.distanceBlockLength == 0) {
decodeDistanceBlockSwitch(s);
}
s.distanceBlockLength--;
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
let distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 255;
distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
if (distanceCode < 16) {
let index = s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode] & 3;
s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
if (s.distance < 0) {
throw "Negative distance";
}
} else {
let extraBits = s.distExtraBits[distanceCode];
let bits;
if (s.bitOffset + extraBits <= 32) {
bits = readFewBits(s, extraBits);
} else {
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
bits = extraBits <= 16 ? readFewBits(s, extraBits) : readManyBits(s, extraBits);
}
s.distance = s.distOffset[distanceCode] + (bits << s.distancePostfixBits);
}
}
if (s.maxDistance != s.maxBackwardDistance && s.pos < s.maxBackwardDistance) {
s.maxDistance = s.pos;
} else {
s.maxDistance = s.maxBackwardDistance;
}
if (s.distance > s.maxDistance) {
s.runningState = 9;
continue;
}
if (distanceCode > 0) {
s.distRbIdx = s.distRbIdx + 1 & 3;
s.rings[s.distRbIdx] = s.distance;
}
if (s.copyLength > s.metaBlockLength) {
throw "Invalid backward reference";
}
s.j = 0;
s.runningState = 8;
case 8:
let src = s.pos - s.distance & ringBufferMask;
let dst = s.pos;
let copyLength = s.copyLength - s.j;
let srcEnd = src + copyLength;
let dstEnd = dst + copyLength;
if (srcEnd < ringBufferMask && dstEnd < ringBufferMask) {
if (copyLength < 12 || srcEnd > dst && dstEnd > src) {
for (let k = 0; k < copyLength; k += 4) {
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
}
} else {
ringBuffer.copyWithin(dst, src, srcEnd);
}
s.j += copyLength;
s.metaBlockLength -= copyLength;
s.pos += copyLength;
} else {
for (; s.j < s.copyLength; ) {
ringBuffer[s.pos] = ringBuffer[s.pos - s.distance & ringBufferMask];
s.metaBlockLength--;
s.pos++;
s.j++;
if (s.pos >= fence) {
s.nextRunningState = 8;
s.runningState = 12;
break;
}
}
}
if (s.runningState == 8) {
s.runningState = 4;
}
continue;
case 9:
doUseDictionary(s, fence);
continue;
case 14:
s.pos += copyFromCompoundDictionary(s, fence);
if (s.pos >= fence) {
s.nextRunningState = 14;
s.runningState = 12;
return;
}
s.runningState = 4;
continue;
case 5:
while (s.metaBlockLength > 0) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
if (s.bitOffset >= 16) {
s.accumulator32 = s.shortBuffer[s.halfOffset++] << 16 | s.accumulator32 >>> 16;
s.bitOffset -= 16;
}
readFewBits(s, 8);
s.metaBlockLength--;
}
s.runningState = 2;
continue;
case 6:
copyUncompressedData(s);
continue;
case 12:
s.ringBufferBytesReady = min(s.pos, s.ringBufferSize);
s.runningState = 13;
case 13:
if (writeRingBuffer(s) == 0) {
return;
}
if (s.pos >= s.maxBackwardDistance) {
s.maxDistance = s.maxBackwardDistance;
}
if (s.pos >= s.ringBufferSize) {
if (s.pos > s.ringBufferSize) {
ringBuffer.copyWithin(0, s.ringBufferSize, s.pos);
}
s.pos &= ringBufferMask;
s.ringBufferBytesWritten = 0;
}
s.runningState = s.nextRunningState;
continue;
default:
throw "Unexpected state " + s.runningState;
}
}
if (s.runningState == 10) {
if (s.metaBlockLength < 0) {
throw "Invalid metablock length";
}
jumpToByteBoundary(s);
checkHealth(s, 1);
}
}