UNPKG

@loaders.gl/compression

Version:

Decompression and compression plugins for loaders.gl

4 lines 307 kB
{ "version": 3, "sources": ["index.js", "lib/compression.js", "lib/no-compression.js", "lib/deflate-compression.js", "lib/gzip-compression.js", "lib/brotli-compression.js", "brotli/decode.js", "lib/snappy-compression.js", "lib/lz4-compression.js", "lib/zstd-compression.js", "lib/lzo-compression.js", "compress-on-worker.js"], "sourcesContent": ["// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nexport { Compression } from \"./lib/compression.js\";\nexport { NoCompression } from \"./lib/no-compression.js\";\nexport { DeflateCompression } from \"./lib/deflate-compression.js\";\nexport { GZipCompression } from \"./lib/gzip-compression.js\";\nexport { BrotliCompression } from \"./lib/brotli-compression.js\";\nexport { SnappyCompression } from \"./lib/snappy-compression.js\";\nexport { LZ4Compression } from \"./lib/lz4-compression.js\";\nexport { ZstdCompression } from \"./lib/zstd-compression.js\";\nexport { LZOCompression } from \"./lib/lzo-compression.js\";\nexport { CompressionWorker, compressOnWorker } from \"./compress-on-worker.js\";\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n// Compression interface\nimport { concatenateArrayBuffersAsync, registerJSModules } from '@loaders.gl/loader-utils';\n/** Compression */\nexport class Compression {\n constructor(options) {\n this.compressBatches = this.compressBatches.bind(this);\n this.decompressBatches = this.decompressBatches.bind(this);\n }\n /** Preloads any dynamic libraries. May enable sync functions */\n async preload(modules = {}) {\n registerJSModules(modules);\n return;\n }\n /** Asynchronously compress data */\n async compress(input) {\n await this.preload();\n return this.compressSync(input);\n }\n /** Asynchronously decompress data */\n async decompress(input, size) {\n await this.preload();\n return this.decompressSync(input, size);\n }\n /** Synchronously compress data */\n compressSync(input) {\n throw new Error(`${this.name}: sync compression not supported`);\n }\n /** Synchronously compress data */\n decompressSync(input, size) {\n throw new Error(`${this.name}: sync decompression not supported`);\n }\n /** Compress batches */\n async *compressBatches(asyncIterator) {\n // TODO - implement incremental compression\n const input = await this.concatenate(asyncIterator);\n yield this.compress(input);\n }\n /** Decompress batches */\n async *decompressBatches(asyncIterator) {\n // TODO - implement incremental compression\n const input = await this.concatenate(asyncIterator);\n yield this.decompress(input);\n }\n // HELPERS\n concatenate(asyncIterator) {\n return concatenateArrayBuffersAsync(asyncIterator);\n }\n improveError(error) {\n if (!error.message.includes(this.name)) {\n error.message = `${this.name} ${error.message}`;\n }\n return error;\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { Compression } from \"./compression.js\";\n/**\n * Applies no compression.\n */\nexport class NoCompression extends Compression {\n name = 'uncompressed';\n extensions = [];\n contentEncodings = [];\n isSupported = true;\n options;\n constructor(options) {\n super(options);\n this.options = options || {};\n }\n compressSync(input) {\n return input;\n }\n decompressSync(input) {\n return input;\n }\n async *compressBatches(asyncIterator) {\n return yield* asyncIterator;\n }\n async *decompressBatches(asyncIterator) {\n return yield* asyncIterator;\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { Compression } from \"./compression.js\";\nimport { isBrowser, toArrayBuffer, promisify1 } from '@loaders.gl/loader-utils';\nimport pako from 'pako'; // https://bundlephobia.com/package/pako\nimport zlib from 'zlib';\n/**\n * DEFLATE compression / decompression\n */\nexport class DeflateCompression extends Compression {\n name = 'deflate';\n extensions = [];\n contentEncodings = ['deflate'];\n isSupported = true;\n options;\n _chunks = [];\n constructor(options = {}) {\n super(options);\n this.options = options;\n }\n async compress(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.deflate?.useZlib) {\n const buffer = this.options.deflate?.gzip\n ? await promisify1(zlib.gzip)(input)\n : await promisify1(zlib.deflate)(input);\n return toArrayBuffer(buffer);\n }\n return this.compressSync(input);\n }\n async decompress(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.deflate?.useZlib) {\n const buffer = this.options.deflate?.gzip\n ? await promisify1(zlib.gunzip)(input)\n : await promisify1(zlib.inflate)(input);\n return toArrayBuffer(buffer);\n }\n return this.decompressSync(input);\n }\n compressSync(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.deflate?.useZlib) {\n const buffer = this.options.deflate?.gzip ? zlib.gzipSync(input) : zlib.deflateSync(input);\n return toArrayBuffer(buffer);\n }\n const pakoOptions = this.options?.deflate || {};\n const inputArray = new Uint8Array(input);\n const deflate = this.options?.raw ? pako.deflateRaw : pako.deflate;\n return deflate(inputArray, pakoOptions).buffer;\n }\n decompressSync(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.deflate?.useZlib) {\n const buffer = this.options.deflate?.gzip ? zlib.gunzipSync(input) : zlib.inflateSync(input);\n return toArrayBuffer(buffer);\n }\n const pakoOptions = this.options?.deflate || {};\n const inputArray = new Uint8Array(input);\n const inflate = this.options?.raw ? pako.inflateRaw : pako.inflate;\n return inflate(inputArray, pakoOptions).buffer;\n }\n async *compressBatches(asyncIterator) {\n const pakoOptions = this.options?.deflate || {};\n const pakoProcessor = new pako.Deflate(pakoOptions);\n yield* this.transformBatches(pakoProcessor, asyncIterator);\n }\n async *decompressBatches(asyncIterator) {\n const pakoOptions = this.options?.deflate || {};\n const pakoProcessor = new pako.Inflate(pakoOptions);\n yield* this.transformBatches(pakoProcessor, asyncIterator);\n }\n async *transformBatches(pakoProcessor, asyncIterator) {\n pakoProcessor.onData = this._onData.bind(this);\n pakoProcessor.onEnd = this._onEnd.bind(this);\n for await (const chunk of asyncIterator) {\n const uint8Array = new Uint8Array(chunk);\n const ok = pakoProcessor.push(uint8Array, false); // false -> not last chunk\n if (!ok) {\n throw new Error(`${this._getError()}write`);\n }\n const chunks = this._getChunks();\n yield* chunks;\n }\n // End\n const emptyChunk = new Uint8Array(0);\n const ok = pakoProcessor.push(emptyChunk, true); // true -> last chunk\n if (!ok) {\n // For some reason we get error but it still works???\n // throw new Error(this._getError() + 'end');\n }\n const chunks = this._getChunks();\n yield* chunks;\n }\n _onData(chunk) {\n this._chunks.push(chunk);\n }\n _onEnd(status) {\n if (status !== 0) {\n throw new Error(this._getError(status) + this._chunks.length);\n }\n }\n _getChunks() {\n const chunks = this._chunks;\n this._chunks = [];\n return chunks;\n }\n // TODO - For some reason we don't get the error message from pako in _onEnd?\n _getError(code = 0) {\n const MESSAGES = {\n /* Z_NEED_DICT 2 */\n 2: 'need dictionary',\n /* Z_STREAM_END 1 */\n 1: 'stream end',\n /* Z_OK 0 */\n 0: '',\n /* Z_ERRNO (-1) */\n '-1': 'file error',\n /* Z_STREAM_ERROR (-2) */\n '-2': 'stream error',\n /* Z_DATA_ERROR (-3) */\n '-3': 'data error',\n /* Z_MEM_ERROR (-4) */\n '-4': 'insufficient memory',\n /* Z_BUF_ERROR (-5) */\n '-5': 'buffer error',\n /* Z_VERSION_ERROR (-6) */\n '-6': 'incompatible version'\n };\n return `${this.name}: ${MESSAGES[code]}`;\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { DeflateCompression } from \"./deflate-compression.js\";\n/**\n * GZIP compression / decompression\n */\nexport class GZipCompression extends DeflateCompression {\n name = 'gzip';\n extensions = ['gz', 'gzip'];\n contentEncodings = ['gzip', 'x-gzip'];\n isSupported = true;\n constructor(options) {\n super({ ...options, deflate: { ...options?.gzip, gzip: true } });\n }\n}\n", "// loaders.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\nimport { Compression } from \"./compression.js\";\nimport { isBrowser, toArrayBuffer, registerJSModules, getJSModule, getJSModuleOrNull, promisify1 } from '@loaders.gl/loader-utils';\n// import brotli from 'brotli'; // https://bundlephobia.com/package/brotli\nimport { BrotliDecode } from \"../brotli/decode.js\";\nimport zlib from 'zlib';\nconst DEFAULT_BROTLI_OPTIONS = {\n brotli: {\n mode: 0,\n quality: 8,\n lgwin: 22\n }\n};\n/**\n * brotli compression / decompression\n */\nexport class BrotliCompression extends Compression {\n name = 'brotli';\n extensions = ['br'];\n contentEncodings = ['br'];\n isSupported = true;\n options;\n constructor(options) {\n super(options);\n this.options = options;\n registerJSModules(options?.modules);\n }\n /**\n * brotli is an injectable dependency due to big size\n * @param options\n */\n async preload(modules = {}) {\n registerJSModules(modules);\n }\n async compress(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.brotli?.useZlib) {\n const buffer = await promisify1(zlib.brotliCompress)(input);\n return toArrayBuffer(buffer);\n }\n return this.compressSync(input);\n }\n compressSync(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.brotli?.useZlib) {\n const buffer = zlib.brotliCompressSync(input);\n return toArrayBuffer(buffer);\n }\n const brotliOptions = { ...DEFAULT_BROTLI_OPTIONS.brotli, ...this.options?.brotli };\n const inputArray = new Uint8Array(input);\n const brotli = getJSModule('brotli', this.name);\n // @ts-ignore brotli types state that only Buffers are accepted...\n const outputArray = brotli.compress(inputArray, brotliOptions);\n return outputArray.buffer;\n }\n async decompress(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.brotli?.useZlib) {\n const buffer = await promisify1(zlib.brotliDecompress)(input);\n return toArrayBuffer(buffer);\n }\n return this.decompressSync(input);\n }\n decompressSync(input) {\n // On Node.js we can use built-in zlib\n if (!isBrowser && this.options.brotli?.useZlib) {\n const buffer = zlib.brotliDecompressSync(input);\n return toArrayBuffer(buffer);\n }\n const brotliOptions = { ...DEFAULT_BROTLI_OPTIONS.brotli, ...this.options?.brotli };\n const inputArray = new Uint8Array(input);\n const brotli = getJSModuleOrNull('brotli');\n if (brotli) {\n // @ts-ignore brotli types state that only Buffers are accepted...\n const outputArray = brotli.decompress(inputArray, brotliOptions);\n return outputArray.buffer;\n }\n const outputArray = BrotliDecode(inputArray, undefined);\n return outputArray.buffer;\n }\n}\n", "// @ts-nocheck\n/* eslint-disable */\n// Forked from https://raw.githubusercontent.com/google/brotli/master/js/decode.js\n// A pure javascript decoder is provided\n/* Copyright 2017 Google Inc. All Rights Reserved.\n * Distributed under MIT license.\n * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n */\n/**\n * @typedef {Object} Options\n * @property {?Int8Array} customDictionary\n */\nlet Options;\n/**\n * Private scope / static initializer for decoder.\n *\n * @return {function(!Int8Array, Options=):!Int8Array}\n */\nlet makeBrotliDecode = () => {\n /**\n * @constructor\n * @param {!Int8Array} bytes\n * @struct\n */\n function InputStream(bytes) {\n /** @type {!Int8Array} */\n this.data = bytes;\n /** @type {!number} */\n this.offset = 0;\n }\n /* GENERATED CODE BEGIN */\n /** @type {!Int32Array} */\n let MAX_HUFFMAN_TABLE_SIZE = Int32Array.from([\n 256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822, 854, 886, 920, 952,\n 984, 1016, 1048, 1080\n ]);\n /** @type {!Int32Array} */\n let CODE_LENGTH_CODE_ORDER = Int32Array.from([\n 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15\n ]);\n /** @type {!Int32Array} */\n let DISTANCE_SHORT_CODE_INDEX_OFFSET = Int32Array.from([\n 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3\n ]);\n /** @type {!Int32Array} */\n let DISTANCE_SHORT_CODE_VALUE_OFFSET = Int32Array.from([\n 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3\n ]);\n /** @type {!Int32Array} */\n let FIXED_TABLE = Int32Array.from([\n 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040001, 0x020000,\n 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040005\n ]);\n /** @type {!Int32Array} */\n let BLOCK_LENGTH_OFFSET = Int32Array.from([\n 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497, 753, 1265,\n 2289, 4337, 8433, 16625\n ]);\n /** @type {!Int32Array} */\n let BLOCK_LENGTH_N_BITS = Int32Array.from([\n 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\n ]);\n /** @type {!Int16Array} */\n let INSERT_LENGTH_N_BITS = Int16Array.from([\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05,\n 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0e, 0x18\n ]);\n /** @type {!Int16Array} */\n let COPY_LENGTH_N_BITS = Int16Array.from([\n 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04,\n 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x18\n ]);\n /** @type {!Int16Array} */\n let CMD_LOOKUP = new Int16Array(2816);\n {\n unpackCommandLookupTable(CMD_LOOKUP);\n }\n /**\n * @param {number} i\n * @return {number}\n */\n function log2floor(i) {\n let /** @type{number} */ result = -1;\n let /** @type{number} */ step = 16;\n while (step > 0) {\n if (i >>> step != 0) {\n result += step;\n i = i >>> step;\n }\n step = step >> 1;\n }\n return result + i;\n }\n /**\n * @param {number} npostfix\n * @param {number} ndirect\n * @param {number} maxndistbits\n * @return {number}\n */\n function calculateDistanceAlphabetSize(npostfix, ndirect, maxndistbits) {\n return 16 + ndirect + 2 * (maxndistbits << npostfix);\n }\n /**\n * @param {number} maxDistance\n * @param {number} npostfix\n * @param {number} ndirect\n * @return {number}\n */\n function calculateDistanceAlphabetLimit(maxDistance, npostfix, ndirect) {\n if (maxDistance < ndirect + (2 << npostfix)) {\n throw 'maxDistance is too small';\n }\n let /** @type{number} */ offset = ((maxDistance - ndirect) >> npostfix) + 4;\n let /** @type{number} */ ndistbits = log2floor(offset) - 1;\n let /** @type{number} */ group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1);\n return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + 16;\n }\n /**\n * @param {!Int16Array} cmdLookup\n * @return {void}\n */\n function unpackCommandLookupTable(cmdLookup) {\n let /** @type{!Int16Array} */ insertLengthOffsets = new Int16Array(24);\n let /** @type{!Int16Array} */ copyLengthOffsets = new Int16Array(24);\n copyLengthOffsets[0] = 2;\n for (let /** @type{number} */ i = 0; i < 23; ++i) {\n insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);\n copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);\n }\n for (let /** @type{number} */ cmdCode = 0; cmdCode < 704; ++cmdCode) {\n let /** @type{number} */ rangeIdx = cmdCode >>> 6;\n let /** @type{number} */ distanceContextOffset = -4;\n if (rangeIdx >= 2) {\n rangeIdx -= 2;\n distanceContextOffset = 0;\n }\n let /** @type{number} */ insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);\n let /** @type{number} */ copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);\n let /** @type{number} */ copyLengthOffset = copyLengthOffsets[copyCode];\n let /** @type{number} */ distanceContext = distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);\n let /** @type{number} */ index = cmdCode * 4;\n cmdLookup[index + 0] = INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8);\n cmdLookup[index + 1] = insertLengthOffsets[insertCode];\n cmdLookup[index + 2] = copyLengthOffsets[copyCode];\n cmdLookup[index + 3] = distanceContext;\n }\n }\n /**\n * @param {!State} s\n * @return {number}\n */\n function decodeWindowBits(s) {\n let /** @type{number} */ largeWindowEnabled = s.isLargeWindow;\n s.isLargeWindow = 0;\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n if (readFewBits(s, 1) == 0) {\n return 16;\n }\n let /** @type{number} */ n = readFewBits(s, 3);\n if (n != 0) {\n return 17 + n;\n }\n n = readFewBits(s, 3);\n if (n != 0) {\n if (n == 1) {\n if (largeWindowEnabled == 0) {\n return -1;\n }\n s.isLargeWindow = 1;\n if (readFewBits(s, 1) == 1) {\n return -1;\n }\n n = readFewBits(s, 6);\n if (n < 10 || n > 30) {\n return -1;\n }\n return n;\n }\n else {\n return 8 + n;\n }\n }\n return 17;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function enableEagerOutput(s) {\n if (s.runningState != 1) {\n throw 'State MUST be freshly initialized';\n }\n s.isEager = 1;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function enableLargeWindow(s) {\n if (s.runningState != 1) {\n throw 'State MUST be freshly initialized';\n }\n s.isLargeWindow = 1;\n }\n /**\n * @param {!State} s\n * @param {!Int8Array} data\n * @return {void}\n */\n function attachDictionaryChunk(s, data) {\n if (s.runningState != 1) {\n throw 'State MUST be freshly initialized';\n }\n if (s.cdNumChunks == 0) {\n s.cdChunks = new Array(16);\n s.cdChunkOffsets = new Int32Array(16);\n s.cdBlockBits = -1;\n }\n if (s.cdNumChunks == 15) {\n throw 'Too many dictionary chunks';\n }\n s.cdChunks[s.cdNumChunks] = data;\n s.cdNumChunks++;\n s.cdTotalSize += data.length;\n s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;\n }\n /**\n * @param {!State} s\n * @param {!InputStream} input\n * @return {void}\n */\n function initState(s, input) {\n if (s.runningState != 0) {\n throw 'State MUST be uninitialized';\n }\n s.blockTrees = new Int32Array(3091);\n s.blockTrees[0] = 7;\n s.distRbIdx = 3;\n let /** @type{number} */ maxDistanceAlphabetLimit = calculateDistanceAlphabetLimit(0x7ffffffc, 3, 15 << 3);\n s.distExtraBits = new Int8Array(maxDistanceAlphabetLimit);\n s.distOffset = new Int32Array(maxDistanceAlphabetLimit);\n s.input = input;\n initBitReader(s);\n s.runningState = 1;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function close(s) {\n if (s.runningState == 0) {\n throw 'State MUST be initialized';\n }\n if (s.runningState == 11) {\n return;\n }\n s.runningState = 11;\n if (s.input != null) {\n closeInput(s.input);\n s.input = null;\n }\n }\n /**\n * @param {!State} s\n * @return {number}\n */\n function decodeVarLenUnsignedByte(s) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n if (readFewBits(s, 1) != 0) {\n let /** @type{number} */ n = readFewBits(s, 3);\n if (n == 0) {\n return 1;\n }\n else {\n return readFewBits(s, n) + (1 << n);\n }\n }\n return 0;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function decodeMetaBlockLength(s) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n s.inputEnd = readFewBits(s, 1);\n s.metaBlockLength = 0;\n s.isUncompressed = 0;\n s.isMetadata = 0;\n if (s.inputEnd != 0 && readFewBits(s, 1) != 0) {\n return;\n }\n let /** @type{number} */ sizeNibbles = readFewBits(s, 2) + 4;\n if (sizeNibbles == 7) {\n s.isMetadata = 1;\n if (readFewBits(s, 1) != 0) {\n throw 'Corrupted reserved bit';\n }\n let /** @type{number} */ sizeBytes = readFewBits(s, 2);\n if (sizeBytes == 0) {\n return;\n }\n for (let /** @type{number} */ i = 0; i < sizeBytes; i++) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ bits = readFewBits(s, 8);\n if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {\n throw 'Exuberant nibble';\n }\n s.metaBlockLength |= bits << (i * 8);\n }\n }\n else {\n for (let /** @type{number} */ i = 0; i < sizeNibbles; i++) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ bits = readFewBits(s, 4);\n if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {\n throw 'Exuberant nibble';\n }\n s.metaBlockLength |= bits << (i * 4);\n }\n }\n s.metaBlockLength++;\n if (s.inputEnd == 0) {\n s.isUncompressed = readFewBits(s, 1);\n }\n }\n /**\n * @param {!Int32Array} tableGroup\n * @param {number} tableIdx\n * @param {!State} s\n * @return {number}\n */\n function readSymbol(tableGroup, tableIdx, s) {\n let /** @type{number} */ offset = tableGroup[tableIdx];\n let /** @type{number} */ val = s.accumulator32 >>> s.bitOffset;\n offset += val & 0xff;\n let /** @type{number} */ bits = tableGroup[offset] >> 16;\n let /** @type{number} */ sym = tableGroup[offset] & 0xffff;\n if (bits <= 8) {\n s.bitOffset += bits;\n return sym;\n }\n offset += sym;\n let /** @type{number} */ mask = (1 << bits) - 1;\n offset += (val & mask) >>> 8;\n s.bitOffset += (tableGroup[offset] >> 16) + 8;\n return tableGroup[offset] & 0xffff;\n }\n /**\n * @param {!Int32Array} tableGroup\n * @param {number} tableIdx\n * @param {!State} s\n * @return {number}\n */\n function readBlockLength(tableGroup, tableIdx, s) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ code = readSymbol(tableGroup, tableIdx, s);\n let /** @type{number} */ n = BLOCK_LENGTH_N_BITS[code];\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n return BLOCK_LENGTH_OFFSET[code] + (n <= 16 ? readFewBits(s, n) : readManyBits(s, n));\n }\n /**\n * @param {!Int32Array} v\n * @param {number} index\n * @return {void}\n */\n function moveToFront(v, index) {\n let /** @type{number} */ value = v[index];\n for (; index > 0; index--) {\n v[index] = v[index - 1];\n }\n v[0] = value;\n }\n /**\n * @param {!Int8Array} v\n * @param {number} vLen\n * @return {void}\n */\n function inverseMoveToFrontTransform(v, vLen) {\n let /** @type{!Int32Array} */ mtf = new Int32Array(256);\n for (let /** @type{number} */ i = 0; i < 256; i++) {\n mtf[i] = i;\n }\n for (let /** @type{number} */ i = 0; i < vLen; i++) {\n let /** @type{number} */ index = v[i] & 0xff;\n v[i] = mtf[index];\n if (index != 0) {\n moveToFront(mtf, index);\n }\n }\n }\n /**\n * @param {!Int32Array} codeLengthCodeLengths\n * @param {number} numSymbols\n * @param {!Int32Array} codeLengths\n * @param {!State} s\n * @return {void}\n */\n function readHuffmanCodeLengths(codeLengthCodeLengths, numSymbols, codeLengths, s) {\n let /** @type{number} */ symbol = 0;\n let /** @type{number} */ prevCodeLen = 8;\n let /** @type{number} */ repeat = 0;\n let /** @type{number} */ repeatCodeLen = 0;\n let /** @type{number} */ space = 32768;\n let /** @type{!Int32Array} */ table = new Int32Array(32 + 1);\n let /** @type{number} */ tableIdx = table.length - 1;\n buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, 18);\n while (symbol < numSymbols && space > 0) {\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ p = (s.accumulator32 >>> s.bitOffset) & 31;\n s.bitOffset += table[p] >> 16;\n let /** @type{number} */ codeLen = table[p] & 0xffff;\n if (codeLen < 16) {\n repeat = 0;\n codeLengths[symbol++] = codeLen;\n if (codeLen != 0) {\n prevCodeLen = codeLen;\n space -= 32768 >> codeLen;\n }\n }\n else {\n let /** @type{number} */ extraBits = codeLen - 14;\n let /** @type{number} */ newLen = 0;\n if (codeLen == 16) {\n newLen = prevCodeLen;\n }\n if (repeatCodeLen != newLen) {\n repeat = 0;\n repeatCodeLen = newLen;\n }\n let /** @type{number} */ oldRepeat = repeat;\n if (repeat > 0) {\n repeat -= 2;\n repeat <<= extraBits;\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n repeat += readFewBits(s, extraBits) + 3;\n let /** @type{number} */ repeatDelta = repeat - oldRepeat;\n if (symbol + repeatDelta > numSymbols) {\n throw 'symbol + repeatDelta > numSymbols';\n }\n for (let /** @type{number} */ i = 0; i < repeatDelta; i++) {\n codeLengths[symbol++] = repeatCodeLen;\n }\n if (repeatCodeLen != 0) {\n space -= repeatDelta << (15 - repeatCodeLen);\n }\n }\n }\n if (space != 0) {\n throw 'Unused space';\n }\n codeLengths.fill(0, symbol, numSymbols);\n }\n /**\n * @param {!Int32Array} symbols\n * @param {number} length\n * @return {void}\n */\n function checkDupes(symbols, length) {\n for (let /** @type{number} */ i = 0; i < length - 1; ++i) {\n for (let /** @type{number} */ j = i + 1; j < length; ++j) {\n if (symbols[i] == symbols[j]) {\n throw 'Duplicate simple Huffman code symbol';\n }\n }\n }\n }\n /**\n * @param {number} alphabetSizeMax\n * @param {number} alphabetSizeLimit\n * @param {!Int32Array} tableGroup\n * @param {number} tableIdx\n * @param {!State} s\n * @return {number}\n */\n function readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {\n let /** @type{!Int32Array} */ codeLengths = new Int32Array(alphabetSizeLimit);\n let /** @type{!Int32Array} */ symbols = new Int32Array(4);\n let /** @type{number} */ maxBits = 1 + log2floor(alphabetSizeMax - 1);\n let /** @type{number} */ numSymbols = readFewBits(s, 2) + 1;\n for (let /** @type{number} */ i = 0; i < numSymbols; i++) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ symbol = readFewBits(s, maxBits);\n if (symbol >= alphabetSizeLimit) {\n throw \"Can't readHuffmanCode\";\n }\n symbols[i] = symbol;\n }\n checkDupes(symbols, numSymbols);\n let /** @type{number} */ histogramId = numSymbols;\n if (numSymbols == 4) {\n histogramId += readFewBits(s, 1);\n }\n switch (histogramId) {\n case 1:\n codeLengths[symbols[0]] = 1;\n break;\n case 2:\n codeLengths[symbols[0]] = 1;\n codeLengths[symbols[1]] = 1;\n break;\n case 3:\n codeLengths[symbols[0]] = 1;\n codeLengths[symbols[1]] = 2;\n codeLengths[symbols[2]] = 2;\n break;\n case 4:\n codeLengths[symbols[0]] = 2;\n codeLengths[symbols[1]] = 2;\n codeLengths[symbols[2]] = 2;\n codeLengths[symbols[3]] = 2;\n break;\n case 5:\n codeLengths[symbols[0]] = 1;\n codeLengths[symbols[1]] = 2;\n codeLengths[symbols[2]] = 3;\n codeLengths[symbols[3]] = 3;\n break;\n default:\n break;\n }\n return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);\n }\n /**\n * @param {number} alphabetSizeLimit\n * @param {number} skip\n * @param {!Int32Array} tableGroup\n * @param {number} tableIdx\n * @param {!State} s\n * @return {number}\n */\n function readComplexHuffmanCode(alphabetSizeLimit, skip, tableGroup, tableIdx, s) {\n let /** @type{!Int32Array} */ codeLengths = new Int32Array(alphabetSizeLimit);\n let /** @type{!Int32Array} */ codeLengthCodeLengths = new Int32Array(18);\n let /** @type{number} */ space = 32;\n let /** @type{number} */ numCodes = 0;\n for (let /** @type{number} */ i = skip; i < 18 && space > 0; i++) {\n let /** @type{number} */ codeLenIdx = CODE_LENGTH_CODE_ORDER[i];\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ p = (s.accumulator32 >>> s.bitOffset) & 15;\n s.bitOffset += FIXED_TABLE[p] >> 16;\n let /** @type{number} */ v = FIXED_TABLE[p] & 0xffff;\n codeLengthCodeLengths[codeLenIdx] = v;\n if (v != 0) {\n space -= 32 >> v;\n numCodes++;\n }\n }\n if (space != 0 && numCodes != 1) {\n throw 'Corrupted Huffman code histogram';\n }\n readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);\n return buildHuffmanTable(tableGroup, tableIdx, 8, codeLengths, alphabetSizeLimit);\n }\n /**\n * @param {number} alphabetSizeMax\n * @param {number} alphabetSizeLimit\n * @param {!Int32Array} tableGroup\n * @param {number} tableIdx\n * @param {!State} s\n * @return {number}\n */\n function readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s) {\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ simpleCodeOrSkip = readFewBits(s, 2);\n if (simpleCodeOrSkip == 1) {\n return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);\n }\n else {\n return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);\n }\n }\n /**\n * @param {number} contextMapSize\n * @param {!Int8Array} contextMap\n * @param {!State} s\n * @return {number}\n */\n function decodeContextMap(contextMapSize, contextMap, s) {\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n let /** @type{number} */ numTrees = decodeVarLenUnsignedByte(s) + 1;\n if (numTrees == 1) {\n contextMap.fill(0, 0, contextMapSize);\n return numTrees;\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ useRleForZeros = readFewBits(s, 1);\n let /** @type{number} */ maxRunLengthPrefix = 0;\n if (useRleForZeros != 0) {\n maxRunLengthPrefix = readFewBits(s, 4) + 1;\n }\n let /** @type{number} */ alphabetSize = numTrees + maxRunLengthPrefix;\n let /** @type{number} */ tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5];\n let /** @type{!Int32Array} */ table = new Int32Array(tableSize + 1);\n let /** @type{number} */ tableIdx = table.length - 1;\n readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);\n for (let /** @type{number} */ i = 0; i < contextMapSize;) {\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ code = readSymbol(table, tableIdx, s);\n if (code == 0) {\n contextMap[i] = 0;\n i++;\n }\n else if (code <= maxRunLengthPrefix) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ reps = (1 << code) + readFewBits(s, code);\n while (reps != 0) {\n if (i >= contextMapSize) {\n throw 'Corrupted context map';\n }\n contextMap[i] = 0;\n i++;\n reps--;\n }\n }\n else {\n contextMap[i] = code - maxRunLengthPrefix;\n i++;\n }\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n if (readFewBits(s, 1) == 1) {\n inverseMoveToFrontTransform(contextMap, contextMapSize);\n }\n return numTrees;\n }\n /**\n * @param {!State} s\n * @param {number} treeType\n * @param {number} numBlockTypes\n * @return {number}\n */\n function decodeBlockTypeAndLength(s, treeType, numBlockTypes) {\n let /** @type{!Int32Array} */ ringBuffers = s.rings;\n let /** @type{number} */ offset = 4 + treeType * 2;\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n let /** @type{number} */ blockType = readSymbol(s.blockTrees, 2 * treeType, s);\n let /** @type{number} */ result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);\n if (blockType == 1) {\n blockType = ringBuffers[offset + 1] + 1;\n }\n else if (blockType == 0) {\n blockType = ringBuffers[offset];\n }\n else {\n blockType -= 2;\n }\n if (blockType >= numBlockTypes) {\n blockType -= numBlockTypes;\n }\n ringBuffers[offset] = ringBuffers[offset + 1];\n ringBuffers[offset + 1] = blockType;\n return result;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function decodeLiteralBlockSwitch(s) {\n s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);\n let /** @type{number} */ literalBlockType = s.rings[5];\n s.contextMapSlice = literalBlockType << 6;\n s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xff;\n let /** @type{number} */ contextMode = s.contextModes[literalBlockType];\n s.contextLookupOffset1 = contextMode << 9;\n s.contextLookupOffset2 = s.contextLookupOffset1 + 256;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function decodeCommandBlockSwitch(s) {\n s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);\n s.commandTreeIdx = s.rings[7];\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function decodeDistanceBlockSwitch(s) {\n s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);\n s.distContextMapSlice = s.rings[9] << 2;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function maybeReallocateRingBuffer(s) {\n let /** @type{number} */ newSize = s.maxRingBufferSize;\n if (newSize > s.expectedTotalSize) {\n let /** @type{number} */ minimalNewSize = s.expectedTotalSize;\n while (newSize >> 1 > minimalNewSize) {\n newSize >>= 1;\n }\n if (s.inputEnd == 0 && newSize < 16384 && s.maxRingBufferSize >= 16384) {\n newSize = 16384;\n }\n }\n if (newSize <= s.ringBufferSize) {\n return;\n }\n let /** @type{number} */ ringBufferSizeWithSlack = newSize + 37;\n let /** @type{!Int8Array} */ newBuffer = new Int8Array(ringBufferSizeWithSlack);\n if (s.ringBuffer.length != 0) {\n newBuffer.set(s.ringBuffer.subarray(0, 0 + s.ringBufferSize), 0);\n }\n s.ringBuffer = newBuffer;\n s.ringBufferSize = newSize;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function readNextMetablockHeader(s) {\n if (s.inputEnd != 0) {\n s.nextRunningState = 10;\n s.runningState = 12;\n return;\n }\n s.literalTreeGroup = new Int32Array(0);\n s.commandTreeGroup = new Int32Array(0);\n s.distanceTreeGroup = new Int32Array(0);\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n decodeMetaBlockLength(s);\n if (s.metaBlockLength == 0 && s.isMetadata == 0) {\n return;\n }\n if (s.isUncompressed != 0 || s.isMetadata != 0) {\n jumpToByteBoundary(s);\n s.runningState = s.isMetadata != 0 ? 5 : 6;\n }\n else {\n s.runningState = 3;\n }\n if (s.isMetadata != 0) {\n return;\n }\n s.expectedTotalSize += s.metaBlockLength;\n if (s.expectedTotalSize > 1 << 30) {\n s.expectedTotalSize = 1 << 30;\n }\n if (s.ringBufferSize < s.maxRingBufferSize) {\n maybeReallocateRingBuffer(s);\n }\n }\n /**\n * @param {!State} s\n * @param {number} treeType\n * @param {number} numBlockTypes\n * @return {number}\n */\n function readMetablockPartition(s, treeType, numBlockTypes) {\n let /** @type{number} */ offset = s.blockTrees[2 * treeType];\n if (numBlockTypes <= 1) {\n s.blockTrees[2 * treeType + 1] = offset;\n s.blockTrees[2 * treeType + 2] = offset;\n return 1 << 28;\n }\n let /** @type{number} */ blockTypeAlphabetSize = numBlockTypes + 2;\n offset += readHuffmanCode(blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);\n s.blockTrees[2 * treeType + 1] = offset;\n let /** @type{number} */ blockLengthAlphabetSize = 26;\n offset += readHuffmanCode(blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);\n s.blockTrees[2 * treeType + 2] = offset;\n return readBlockLength(s.blockTrees, 2 * treeType + 1, s);\n }\n /**\n * @param {!State} s\n * @param {number} alphabetSizeLimit\n * @return {void}\n */\n function calculateDistanceLut(s, alphabetSizeLimit) {\n let /** @type{!Int8Array} */ distExtraBits = s.distExtraBits;\n let /** @type{!Int32Array} */ distOffset = s.distOffset;\n let /** @type{number} */ npostfix = s.distancePostfixBits;\n let /** @type{number} */ ndirect = s.numDirectDistanceCodes;\n let /** @type{number} */ postfix = 1 << npostfix;\n let /** @type{number} */ bits = 1;\n let /** @type{number} */ half = 0;\n let /** @type{number} */ i = 16;\n for (let /** @type{number} */ j = 0; j < ndirect; ++j) {\n distExtraBits[i] = 0;\n distOffset[i] = j + 1;\n ++i;\n }\n while (i < alphabetSizeLimit) {\n let /** @type{number} */ base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;\n for (let /** @type{number} */ j = 0; j < postfix; ++j) {\n distExtraBits[i] = bits;\n distOffset[i] = base + j;\n ++i;\n }\n bits = bits + half;\n half = half ^ 1;\n }\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function readMetablockHuffmanCodesAndContextMaps(s) {\n s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;\n s.literalBlockLength = readMetablockPartition(s, 0, s.numLiteralBlockTypes);\n s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;\n s.commandBlockLength = readMetablockPartition(s, 1, s.numCommandBlockTypes);\n s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;\n s.distanceBlockLength = readMetablockPartition(s, 2, s.numDistanceBlockTypes);\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n s.distancePostfixBits = readFewBits(s, 2);\n s.numDirectDistanceCodes = readFewBits(s, 4) << s.distancePostfixBits;\n s.contextModes = new Int8Array(s.numLiteralBlockTypes);\n for (let /** @type{number} */ i = 0; i < s.numLiteralBlockTypes;) {\n let /** @type{number} */ limit = min(i + 96, s.numLiteralBlockTypes);\n for (; i < limit; ++i) {\n if (s.bitOffset >= 16) {\n s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);\n s.bitOffset -= 16;\n }\n s.contextModes[i] = readFewBits(s, 2);\n }\n if (s.halfOffset > 2030) {\n doReadMoreInput(s);\n }\n }\n s.contextMap = new Int8Array(s.numLiteralBlockTypes << 6);\n let /** @type{number} */ numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << 6, s.contextMap, s);\n s.trivialLiteralContext = 1;\n for (let /** @type{number} */ j = 0; j < s.numLiteralBlockTypes << 6; j++) {\n if (s.contextMap[j] != j >> 6) {\n s.trivialLiteralContext = 0;\n break;\n }\n }\n s.distContextMap = new Int8Array(s.numDistanceBlockTypes << 2);\n let /** @type{number} */ numDistTrees = decodeContextMap(s.numDistanceBlockTypes << 2, s.distContextMap, s);\n s.literalTreeGroup = decodeHuffmanTreeGroup(256, 256, numLiteralTrees, s);\n s.commandTreeGroup = decodeHuffmanTreeGroup(704, 704, s.numCommandBlockTypes, s);\n let /** @type{number} */ distanceAlphabetSizeMax = calculateDistanceAlphabetSize(s.distancePostfixBits, s.numDirectDistanceCodes, 24);\n let /** @type{number} */ distanceAlphabetSizeLimit = distanceAlphabetSizeMax;\n if (s.isLargeWindow == 1) {\n distanceAlphabetSizeMax = calculateDistanceAlphabetSize(s.distancePostfixBits, s.numDirectDistanceCodes, 62);\n distanceAlphabetSizeLimit = calculateDistanceAlphabetLimit(0x7ffffffc, s.distancePostfixBits, s.numDirectDistanceCodes);\n }\n s.distanceTreeGroup = decodeHuffmanTreeGroup(distanceAlphabetSizeMax, distanceAlphabetSizeLimit, numDistTrees, s);\n calculateDistanceLut(s, distanceAlphabetSizeLimit);\n s.contextMapSlice = 0;\n s.distContextMapSlice = 0;\n s.contextLookupOffset1 = s.contextModes[0] * 512;\n s.contextLookupOffset2 = s.contextLookupOffset1 + 256;\n s.literalTreeIdx = 0;\n s.commandTreeIdx = 0;\n s.rings[4] = 1;\n s.rings[5] = 0;\n s.rings[6] = 1;\n s.rings[7] = 0;\n s.rings[8] = 1;\n s.rings[9] = 0;\n }\n /**\n * @param {!State} s\n * @return {void}\n */\n function copyUncompressedData(s) {\n let /** @type{!Int8Array} */ ringBuffer = s.ringBuffer;\n if (s.metaBlockLength <= 0) {\n reload(s);\n s.runningState = 2;\n return;\n }\n let /** @type{number} */ chunkLength = min(s.ringBufferSize - s.pos, s.metaBlockLength);\n copyRawBytes(s, ringBuffer, s.pos, chunkLength);\n s.metaBlockLength -= chunkLength;\n s.pos += chunkLength;\n if (s.pos == s.ringBufferSize) {\n s.nextRunningState = 6;\n s.runningState = 12;\n return;\n }\n reload(s);\n s.runningState = 2;\n }\n /**\n * @param {!State} s\n * @return {number}\n */\n function writeRingBuffer(s) {\n let /** @type{number} */ toWrite = min(s.outputLength - s.outputUsed, s.ringBufferBytesReady - s.ringBufferBytesWritten);\n if (toWrite != 0) {\n s.output.set(s.ringBuffer.subarray(s.ringBufferBytesWritten, s.ringBufferBytesWritten + toWrite), s.outputOffset + s.out