add ts types, port to using luau apis

This commit is contained in:
daimond113 2024-12-26 10:54:20 +01:00
parent cf8e6ba0f7
commit 20d3146428
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
16 changed files with 5235 additions and 5224 deletions

View file

@ -1,28 +1,29 @@
'use strict'; "use strict";
import { DeflateState } from "./zlib/deflate";
const zlib_deflate = require('./zlib/deflate'); import * as zlibDeflate from "./zlib/deflate";
const utils = require('./utils/common'); import { ZStream } from "./zlib/zstream";
const strings = require('./utils/strings');
const msg = require('./zlib/messages');
const ZStream = require('./zlib/zstream');
const toString = Object.prototype.toString;
/* Public constants ==========================================================*/ /* Public constants ==========================================================*/
/* ===========================================================================*/ /* ===========================================================================*/
const { import {
Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH, Z_NO_FLUSH,
Z_OK, Z_STREAM_END, Z_SYNC_FLUSH,
Z_DEFAULT_COMPRESSION, Z_FULL_FLUSH,
Z_DEFAULT_STRATEGY, Z_FINISH,
Z_DEFLATED Z_OK,
} = require('./zlib/constants'); Z_STREAM_END,
Z_DEFAULT_COMPRESSION,
Z_DEFAULT_STRATEGY,
Z_DEFLATED,
} from "./zlib/constants";
import { assign, flattenChunks } from "./utils/common";
import { Uint8Array } from "./utils/buffs";
import messages from "./zlib/messages";
/* ===========================================================================*/ /* ===========================================================================*/
/** /**
* class Deflate * class Deflate
* *
@ -60,7 +61,6 @@ const {
* Error message, if [[Deflate.err]] != 0 * Error message, if [[Deflate.err]] != 0
**/ **/
/** /**
* new Deflate(options) * new Deflate(options)
* - options (Object): zlib deflate options. * - options (Object): zlib deflate options.
@ -108,197 +108,209 @@ const {
* console.log(deflate.result); * console.log(deflate.result);
* ``` * ```
**/ **/
function Deflate(options) {
this.options = utils.assign({
level: Z_DEFAULT_COMPRESSION,
method: Z_DEFLATED,
chunkSize: 16384,
windowBits: 15,
memLevel: 8,
strategy: Z_DEFAULT_STRATEGY
}, options || {});
let opt = this.options; type Options = {
level: number;
method: number;
chunkSize: number;
windowBits: number;
memLevel: number;
strategy: number;
raw: boolean;
gzip: boolean;
header?: DeflateState["gzhead"];
dictionary?: Uint8Array | string;
};
if (opt.raw && (opt.windowBits > 0)) { export class Deflate {
opt.windowBits = -opt.windowBits; public options: Exclude<Options, "dictionary"> & { dictionary?: Uint8Array };
} public err: keyof typeof messages = Z_OK;
public msg?: string;
public ended = false;
public chunks: Uint8Array[] = [];
public strm = new ZStream<DeflateState>();
public result?: buffer;
else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { constructor(options: Partial<Options>) {
opt.windowBits += 16; this.options = assign(
} {
level: Z_DEFAULT_COMPRESSION,
method: Z_DEFLATED,
chunkSize: 16384,
windowBits: 15,
memLevel: 8,
strategy: Z_DEFAULT_STRATEGY,
raw: false,
gzip: false,
},
options || {},
) as unknown as typeof this.options;
this.err = 0; // error code, if happens (0 = Z_OK) let opt = this.options;
this.msg = ''; // error message
this.ended = false; // used to avoid multiple onEnd() calls
this.chunks = []; // chunks of compressed data
this.strm = new ZStream(); if (opt.raw && opt.windowBits > 0) {
this.strm.avail_out = 0; opt.windowBits = -opt.windowBits;
} else if (opt.gzip && opt.windowBits > 0 && opt.windowBits < 16) {
opt.windowBits += 16;
}
let status = zlib_deflate.deflateInit2( if (opt.dictionary) {
this.strm, // Convert data if needed
opt.level, let dict = opt.dictionary;
opt.method, if (typeIs(dict, "string")) {
opt.windowBits, dict = Uint8Array.from(buffer.fromstring(dict));
opt.memLevel, }
opt.strategy
);
if (status !== Z_OK) { opt.dictionary = dict;
throw new Error(msg[status]); }
}
if (opt.header) { this.strm.avail_out = 0;
zlib_deflate.deflateSetHeader(this.strm, opt.header);
}
if (opt.dictionary) { const status = zlibDeflate.deflateInit2(
let dict; this.strm,
// Convert data if needed opt.level,
if (typeof opt.dictionary === 'string') { opt.method,
// If we need to compress text, change encoding to utf8. opt.windowBits,
dict = strings.string2buf(opt.dictionary); opt.memLevel,
} else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { opt.strategy,
dict = new Uint8Array(opt.dictionary); );
} else {
dict = opt.dictionary;
}
status = zlib_deflate.deflateSetDictionary(this.strm, dict); if (status !== Z_OK) {
error(messages[status]);
}
if (status !== Z_OK) { if (opt.header) {
throw new Error(msg[status]); zlibDeflate.deflateSetHeader(this.strm, opt.header);
} }
this._dict_set = true; if (opt.dictionary) {
} const status = zlibDeflate.deflateSetDictionary(this.strm, opt.dictionary);
if (status !== Z_OK) {
error(messages[status]);
}
}
}
/**
* Deflate#push(data[, flush_mode]) -> Boolean
* - data (Uint8Array|ArrayBuffer|String): input data. Strings will be
* converted to utf8 byte sequence.
* - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
* See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
*
* Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
* new compressed chunks. Returns `true` on success. The last data block must
* have `flush_mode` Z_FINISH (or `true`). That will flush internal pending
* buffers and call [[Deflate#onEnd]].
*
* On fail call [[Deflate#onEnd]] with error code and return false.
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
push(data: Uint8Array | string, flush_mode: boolean | number) {
const strm = this.strm;
const { chunkSize } = this.options;
let status, _flush_mode;
if (this.ended) {
return false;
}
if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
// Convert data if needed
if (typeIs(data, "string")) {
strm.input = Uint8Array.from(buffer.fromstring(data));
}
strm.next_in = 0;
strm.avail_in = strm.input.length;
for (;;) {
if (strm.avail_out === 0) {
strm.output = new Uint8Array(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
// Make sure avail_out > 6 to avoid repeating markers
if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {
this.onData(strm.output.subarray(0, strm.next_out));
strm.avail_out = 0;
continue;
}
status = zlibDeflate.deflate(strm, _flush_mode);
// Ended => flush and finish
if (status === Z_STREAM_END) {
if (strm.next_out > 0) {
this.onData(strm.output.subarray(0, strm.next_out));
}
const status = zlibDeflate.deflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return status === Z_OK;
}
// Flush if out buffer full
if (strm.avail_out === 0) {
this.onData(strm.output);
continue;
}
// Flush if requested and has data
if (_flush_mode > 0 && strm.next_out > 0) {
this.onData(strm.output.subarray(0, strm.next_out));
strm.avail_out = 0;
continue;
}
if (strm.avail_in === 0) break;
}
return true;
}
/**
* Deflate#onData(chunk) -> Void
* - chunk (Uint8Array): output data.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
onData(chunk: Uint8Array) {
this.chunks.push(chunk);
}
/**
* Deflate#onEnd(status) -> Void
* - status (Number): deflate status. 0 (Z_OK) on success,
* other if not.
*
* Called once after you tell deflate that the input stream is
* complete (Z_FINISH). By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
onEnd(status: keyof typeof messages) {
// On success - join
if (status === Z_OK) {
this.result = flattenChunks(this.chunks.map((chunk) => chunk.buf));
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
}
} }
/**
* Deflate#push(data[, flush_mode]) -> Boolean
* - data (Uint8Array|ArrayBuffer|String): input data. Strings will be
* converted to utf8 byte sequence.
* - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.
* See constants. Skipped or `false` means Z_NO_FLUSH, `true` means Z_FINISH.
*
* Sends input data to deflate pipe, generating [[Deflate#onData]] calls with
* new compressed chunks. Returns `true` on success. The last data block must
* have `flush_mode` Z_FINISH (or `true`). That will flush internal pending
* buffers and call [[Deflate#onEnd]].
*
* On fail call [[Deflate#onEnd]] with error code and return false.
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
Deflate.prototype.push = function (data, flush_mode) {
const strm = this.strm;
const chunkSize = this.options.chunkSize;
let status, _flush_mode;
if (this.ended) { return false; }
if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
// Convert data if needed
if (typeof data === 'string') {
// If we need to compress text, change encoding to utf8.
strm.input = strings.string2buf(data);
} else if (toString.call(data) === '[object ArrayBuffer]') {
strm.input = new Uint8Array(data);
} else {
strm.input = data;
}
strm.next_in = 0;
strm.avail_in = strm.input.length;
for (;;) {
if (strm.avail_out === 0) {
strm.output = new Uint8Array(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
// Make sure avail_out > 6 to avoid repeating markers
if ((_flush_mode === Z_SYNC_FLUSH || _flush_mode === Z_FULL_FLUSH) && strm.avail_out <= 6) {
this.onData(strm.output.subarray(0, strm.next_out));
strm.avail_out = 0;
continue;
}
status = zlib_deflate.deflate(strm, _flush_mode);
// Ended => flush and finish
if (status === Z_STREAM_END) {
if (strm.next_out > 0) {
this.onData(strm.output.subarray(0, strm.next_out));
}
status = zlib_deflate.deflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return status === Z_OK;
}
// Flush if out buffer full
if (strm.avail_out === 0) {
this.onData(strm.output);
continue;
}
// Flush if requested and has data
if (_flush_mode > 0 && strm.next_out > 0) {
this.onData(strm.output.subarray(0, strm.next_out));
strm.avail_out = 0;
continue;
}
if (strm.avail_in === 0) break;
}
return true;
};
/**
* Deflate#onData(chunk) -> Void
* - chunk (Uint8Array): output data.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
Deflate.prototype.onData = function (chunk) {
this.chunks.push(chunk);
};
/**
* Deflate#onEnd(status) -> Void
* - status (Number): deflate status. 0 (Z_OK) on success,
* other if not.
*
* Called once after you tell deflate that the input stream is
* complete (Z_FINISH). By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
Deflate.prototype.onEnd = function (status) {
// On success - join
if (status === Z_OK) {
this.result = utils.flattenChunks(this.chunks);
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
};
/** /**
* deflate(data[, options]) -> Uint8Array * deflate(data[, options]) -> Uint8Array
* - data (Uint8Array|ArrayBuffer|String): input data to compress. * - data (Uint8Array|ArrayBuffer|String): input data to compress.
@ -331,18 +343,19 @@ Deflate.prototype.onEnd = function (status) {
* console.log(pako.deflate(data)); * console.log(pako.deflate(data));
* ``` * ```
**/ **/
function deflate(input, options) { export function deflate(input: Uint8Array, options: Partial<Options> = {}) {
const deflator = new Deflate(options); const deflator = new Deflate(options);
deflator.push(input, true); deflator.push(input, true);
// That will never happens, if you don't cheat with options :) // That will never happens, if you don't cheat with options :)
if (deflator.err) { throw deflator.msg || msg[deflator.err]; } if (deflator.err) {
error(deflator.msg || messages[deflator.err]);
}
return deflator.result; return deflator.result;
} }
/** /**
* deflateRaw(data[, options]) -> Uint8Array * deflateRaw(data[, options]) -> Uint8Array
* - data (Uint8Array|ArrayBuffer|String): input data to compress. * - data (Uint8Array|ArrayBuffer|String): input data to compress.
@ -351,30 +364,10 @@ function deflate(input, options) {
* The same as [[deflate]], but creates raw data, without wrapper * The same as [[deflate]], but creates raw data, without wrapper
* (header and adler32 crc). * (header and adler32 crc).
**/ **/
function deflateRaw(input, options) { export function deflateRaw(input: Uint8Array, options: Exclude<Partial<Options>, "raw"> = {}) {
options = options || {}; options = options || {};
options.raw = true; options.raw = true;
return deflate(input, options); return deflate(input, options);
} }
export * from "./zlib/constants";
/**
* gzip(data[, options]) -> Uint8Array
* - data (Uint8Array|ArrayBuffer|String): input data to compress.
* - options (Object): zlib deflate options.
*
* The same as [[deflate]], but create gzip wrapper instead of
* deflate one.
**/
function gzip(input, options) {
options = options || {};
options.gzip = true;
return deflate(input, options);
}
module.exports.Deflate = Deflate;
module.exports.deflate = deflate;
module.exports.deflateRaw = deflateRaw;
module.exports.gzip = gzip;
module.exports.constants = require('./zlib/constants');

View file

@ -1,26 +1,29 @@
'use strict'; "use strict";
import { type InflateState } from "./zlib/inflate";
const zlib_inflate = require('./zlib/inflate'); import * as zlibInflate from "./zlib/inflate";
const utils = require('./utils/common'); import { ZStream } from "./zlib/zstream";
const strings = require('./utils/strings'); import { GZheader } from "./zlib/gzheader";
const msg = require('./zlib/messages');
const ZStream = require('./zlib/zstream');
const GZheader = require('./zlib/gzheader');
const toString = Object.prototype.toString;
/* Public constants ==========================================================*/ /* Public constants ==========================================================*/
/* ===========================================================================*/ /* ===========================================================================*/
const { import {
Z_NO_FLUSH, Z_FINISH, Z_NO_FLUSH,
Z_OK, Z_STREAM_END, Z_NEED_DICT, Z_STREAM_ERROR, Z_DATA_ERROR, Z_MEM_ERROR Z_FINISH,
} = require('./zlib/constants'); Z_OK,
Z_STREAM_END,
Z_NEED_DICT,
Z_STREAM_ERROR,
Z_DATA_ERROR,
Z_MEM_ERROR,
} from "./zlib/constants";
import { Uint8Array } from "./utils/buffs";
import { assign, flattenChunks } from "./utils/common";
import messages from "./zlib/messages";
/* ===========================================================================*/ /* ===========================================================================*/
/** /**
* class Inflate * class Inflate
* *
@ -56,7 +59,6 @@ const {
* Error message, if [[Inflate.err]] != 0 * Error message, if [[Inflate.err]] != 0
**/ **/
/** /**
* new Inflate(options) * new Inflate(options)
* - options (Object): zlib inflate options. * - options (Object): zlib inflate options.
@ -98,244 +100,232 @@ const {
* console.log(inflate.result); * console.log(inflate.result);
* ``` * ```
**/ **/
function Inflate(options) {
this.options = utils.assign({
chunkSize: 1024 * 64,
windowBits: 15,
to: ''
}, options || {});
const opt = this.options; type Options = {
chunkSize: number;
windowBits: number;
to: string;
raw: boolean;
dictionary?: string | Uint8Array;
};
// Force window size for `raw` data, if not set directly, export class Inflate {
// because we have no header for autodetect. public options: Exclude<Options, "dictionary"> & { dictionary?: Uint8Array };
if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { public err: keyof typeof messages = Z_OK;
opt.windowBits = -opt.windowBits; public msg?: string;
if (opt.windowBits === 0) { opt.windowBits = -15; } public ended = false;
} public chunks: Uint8Array[] = [];
public strm = new ZStream<InflateState>();
public header = new GZheader();
public result?: buffer | string;
// If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate constructor(options?: Partial<Options>) {
if ((opt.windowBits >= 0) && (opt.windowBits < 16) && this.options = assign(
!(options && options.windowBits)) { {
opt.windowBits += 32; chunkSize: 1024 * 64,
} windowBits: 15,
to: "",
raw: false,
dictionary: undefined,
},
options ?? {},
) as unknown as typeof this.options;
// Gzip header has no info about windows size, we can do autodetect only const opt = this.options;
// for deflate. So, if window size not set, force it to max when gzip possible
if ((opt.windowBits > 15) && (opt.windowBits < 48)) {
// bit 3 (16) -> gzipped data
// bit 4 (32) -> autodetect gzip/deflate
if ((opt.windowBits & 15) === 0) {
opt.windowBits |= 15;
}
}
this.err = 0; // error code, if happens (0 = Z_OK) // Force window size for `raw` data, if not set directly,
this.msg = ''; // error message // because we have no header for autodetect.
this.ended = false; // used to avoid multiple onEnd() calls if (opt.raw && opt.windowBits >= 0 && opt.windowBits < 16) {
this.chunks = []; // chunks of compressed data opt.windowBits = -opt.windowBits;
if (opt.windowBits === 0) {
opt.windowBits = -15;
}
}
this.strm = new ZStream(); // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate
this.strm.avail_out = 0; if (opt.windowBits >= 0 && opt.windowBits < 16 && !(options && options.windowBits)) {
opt.windowBits += 32;
}
let status = zlib_inflate.inflateInit2( // Gzip header has no info about windows size, we can do autodetect only
this.strm, // for deflate. So, if window size not set, force it to max when gzip possible
opt.windowBits if (opt.windowBits > 15 && opt.windowBits < 48) {
); // bit 3 (16) -> gzipped data
// bit 4 (32) -> autodetect gzip/deflate
if ((opt.windowBits & 15) === 0) {
opt.windowBits |= 15;
}
}
if (status !== Z_OK) { if (opt.dictionary) {
throw new Error(msg[status]); // Convert data if needed
} let dict = opt.dictionary;
if (typeIs(dict, "string")) {
dict = Uint8Array.from(buffer.fromstring(dict));
}
this.header = new GZheader(); opt.dictionary = dict;
}
zlib_inflate.inflateGetHeader(this.strm, this.header); this.strm.avail_out = 0;
// Setup dictionary const { windowBits, dictionary, raw } = opt;
if (opt.dictionary) { const status = zlibInflate.inflateInit2(this.strm, windowBits);
// Convert data if needed
if (typeof opt.dictionary === 'string') { if (status !== Z_OK) {
opt.dictionary = strings.string2buf(opt.dictionary); error(messages[status]);
} else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { }
opt.dictionary = new Uint8Array(opt.dictionary);
} zlibInflate.inflateGetHeader(this.strm, this.header);
if (opt.raw) { //In raw mode we need to set the dictionary early
status = zlib_inflate.inflateSetDictionary(this.strm, opt.dictionary); if (dictionary && raw) {
if (status !== Z_OK) { //In raw mode we need to set the dictionary early
throw new Error(msg[status]); const status = zlibInflate.inflateSetDictionary(this.strm, dictionary);
} if (status !== Z_OK) {
} error(messages[status]);
} }
}
}
/**
* Inflate#push(data[, flush_mode]) -> Boolean
* - data (Uint8Array|ArrayBuffer): input data
* - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
* flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
* `true` means Z_FINISH.
*
* Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
* new output chunks. Returns `true` on success. If end of stream detected,
* [[Inflate#onEnd]] will be called.
*
* `flush_mode` is not needed for normal operation, because end of stream
* detected automatically. You may try to use it for advanced things, but
* this functionality was not tested.
*
* On fail call [[Inflate#onEnd]] with error code and return false.
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
push(data: Uint8Array, flush_mode: number | boolean) {
const strm = this.strm;
const { chunkSize, dictionary } = this.options;
let status, _flush_mode, last_avail_out;
if (this.ended) return false;
if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
strm.input = data;
strm.next_in = 0;
strm.avail_in = strm.input.length;
for (;;) {
if (strm.avail_out === 0) {
strm.output = new Uint8Array(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
status = zlibInflate.inflate(strm, _flush_mode);
if (status === Z_NEED_DICT && dictionary) {
status = zlibInflate.inflateSetDictionary(strm, dictionary);
if (status === Z_OK) {
status = zlibInflate.inflate(strm, _flush_mode);
} else if (status === Z_DATA_ERROR) {
// Replace code with more verbose
status = Z_NEED_DICT;
}
}
// Skip snyc markers if more data follows and not raw mode
while (strm.avail_in > 0 && status === Z_STREAM_END && strm.state.wrap > 0 && data[strm.next_in] !== 0) {
zlibInflate.inflateReset(strm);
status = zlibInflate.inflate(strm, _flush_mode);
}
switch (status) {
case Z_STREAM_ERROR:
case Z_DATA_ERROR:
case Z_NEED_DICT:
case Z_MEM_ERROR:
this.onEnd(status);
this.ended = true;
return false;
}
// Remember real `avail_out` value, because we may patch out buffer content
// to align utf8 strings boundaries.
last_avail_out = strm.avail_out;
if (strm.next_out && (strm.avail_out === 0 || status === Z_STREAM_END)) {
this.onData(
strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out),
);
}
// Must repeat iteration if out buffer is full
if (status === Z_OK && last_avail_out === 0) continue;
// Finalize if end of stream reached.
if (status === Z_STREAM_END) {
const status = zlibInflate.inflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return true;
}
if (strm.avail_in === 0) break;
}
return true;
}
/**
* Inflate#onData(chunk) -> Void
* - chunk (Uint8Array|String): output data. When string output requested,
* each chunk will be string.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
onData(chunk: Uint8Array) {
this.chunks.push(chunk);
}
/**
* Inflate#onEnd(status) -> Void
* - status (Number): inflate status. 0 (Z_OK) on success,
* other if not.
*
* Called either after you tell inflate that the input stream is
* complete (Z_FINISH). By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
onEnd(status: keyof typeof messages) {
// On success - join
if (status === Z_OK) {
if (this.options.to === "string") {
this.result = this.chunks.join("");
} else {
this.result = flattenChunks(this.chunks.map((chunk) => chunk.buf));
}
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
}
} }
/**
* Inflate#push(data[, flush_mode]) -> Boolean
* - data (Uint8Array|ArrayBuffer): input data
* - flush_mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE
* flush modes. See constants. Skipped or `false` means Z_NO_FLUSH,
* `true` means Z_FINISH.
*
* Sends input data to inflate pipe, generating [[Inflate#onData]] calls with
* new output chunks. Returns `true` on success. If end of stream detected,
* [[Inflate#onEnd]] will be called.
*
* `flush_mode` is not needed for normal operation, because end of stream
* detected automatically. You may try to use it for advanced things, but
* this functionality was not tested.
*
* On fail call [[Inflate#onEnd]] with error code and return false.
*
* ##### Example
*
* ```javascript
* push(chunk, false); // push one of data chunks
* ...
* push(chunk, true); // push last chunk
* ```
**/
Inflate.prototype.push = function (data, flush_mode) {
const strm = this.strm;
const chunkSize = this.options.chunkSize;
const dictionary = this.options.dictionary;
let status, _flush_mode, last_avail_out;
if (this.ended) return false;
if (flush_mode === ~~flush_mode) _flush_mode = flush_mode;
else _flush_mode = flush_mode === true ? Z_FINISH : Z_NO_FLUSH;
// Convert data if needed
if (toString.call(data) === '[object ArrayBuffer]') {
strm.input = new Uint8Array(data);
} else {
strm.input = data;
}
strm.next_in = 0;
strm.avail_in = strm.input.length;
for (;;) {
if (strm.avail_out === 0) {
strm.output = new Uint8Array(chunkSize);
strm.next_out = 0;
strm.avail_out = chunkSize;
}
status = zlib_inflate.inflate(strm, _flush_mode);
if (status === Z_NEED_DICT && dictionary) {
status = zlib_inflate.inflateSetDictionary(strm, dictionary);
if (status === Z_OK) {
status = zlib_inflate.inflate(strm, _flush_mode);
} else if (status === Z_DATA_ERROR) {
// Replace code with more verbose
status = Z_NEED_DICT;
}
}
// Skip snyc markers if more data follows and not raw mode
while (strm.avail_in > 0 &&
status === Z_STREAM_END &&
strm.state.wrap > 0 &&
data[strm.next_in] !== 0)
{
zlib_inflate.inflateReset(strm);
status = zlib_inflate.inflate(strm, _flush_mode);
}
switch (status) {
case Z_STREAM_ERROR:
case Z_DATA_ERROR:
case Z_NEED_DICT:
case Z_MEM_ERROR:
this.onEnd(status);
this.ended = true;
return false;
}
// Remember real `avail_out` value, because we may patch out buffer content
// to align utf8 strings boundaries.
last_avail_out = strm.avail_out;
if (strm.next_out) {
if (strm.avail_out === 0 || status === Z_STREAM_END) {
if (this.options.to === 'string') {
let next_out_utf8 = strings.utf8border(strm.output, strm.next_out);
let tail = strm.next_out - next_out_utf8;
let utf8str = strings.buf2string(strm.output, next_out_utf8);
// move tail & realign counters
strm.next_out = tail;
strm.avail_out = chunkSize - tail;
if (tail) strm.output.set(strm.output.subarray(next_out_utf8, next_out_utf8 + tail), 0);
this.onData(utf8str);
} else {
this.onData(strm.output.length === strm.next_out ? strm.output : strm.output.subarray(0, strm.next_out));
}
}
}
// Must repeat iteration if out buffer is full
if (status === Z_OK && last_avail_out === 0) continue;
// Finalize if end of stream reached.
if (status === Z_STREAM_END) {
status = zlib_inflate.inflateEnd(this.strm);
this.onEnd(status);
this.ended = true;
return true;
}
if (strm.avail_in === 0) break;
}
return true;
};
/**
* Inflate#onData(chunk) -> Void
* - chunk (Uint8Array|String): output data. When string output requested,
* each chunk will be string.
*
* By default, stores data blocks in `chunks[]` property and glue
* those in `onEnd`. Override this handler, if you need another behaviour.
**/
Inflate.prototype.onData = function (chunk) {
this.chunks.push(chunk);
};
/**
* Inflate#onEnd(status) -> Void
* - status (Number): inflate status. 0 (Z_OK) on success,
* other if not.
*
* Called either after you tell inflate that the input stream is
* complete (Z_FINISH). By default - join collected chunks,
* free memory and fill `results` / `err` properties.
**/
Inflate.prototype.onEnd = function (status) {
// On success - join
if (status === Z_OK) {
if (this.options.to === 'string') {
this.result = this.chunks.join('');
} else {
this.result = utils.flattenChunks(this.chunks);
}
}
this.chunks = [];
this.err = status;
this.msg = this.strm.msg;
};
/** /**
* inflate(data[, options]) -> Uint8Array|String * inflate(data[, options]) -> Uint8Array|String
* - data (Uint8Array|ArrayBuffer): input data to decompress. * - data (Uint8Array|ArrayBuffer): input data to decompress.
@ -375,18 +365,17 @@ Inflate.prototype.onEnd = function (status) {
* } * }
* ``` * ```
**/ **/
function inflate(input, options) { export function inflate(input: Uint8Array, options: Partial<Options> = {}) {
const inflator = new Inflate(options); const inflator = new Inflate(options);
inflator.push(input); inflator.push(input, true);
// That will never happens, if you don't cheat with options :) // That will never happens, if you don't cheat with options :)
if (inflator.err) throw inflator.msg || msg[inflator.err]; if (inflator.err) error(inflator.msg || messages[inflator.err]);
return inflator.result; return inflator.result;
} }
/** /**
* inflateRaw(data[, options]) -> Uint8Array|String * inflateRaw(data[, options]) -> Uint8Array|String
* - data (Uint8Array|ArrayBuffer): input data to decompress. * - data (Uint8Array|ArrayBuffer): input data to decompress.
@ -395,25 +384,10 @@ function inflate(input, options) {
* The same as [[inflate]], but creates raw data, without wrapper * The same as [[inflate]], but creates raw data, without wrapper
* (header and adler32 crc). * (header and adler32 crc).
**/ **/
function inflateRaw(input, options) { export function inflateRaw(input: Uint8Array, options: Exclude<Partial<Options>, "raw"> = {}) {
options = options || {}; options = options || {};
options.raw = true; options.raw = true;
return inflate(input, options); return inflate(input, options);
} }
export * from "./zlib/constants";
/**
* ungzip(data[, options]) -> Uint8Array|String
* - data (Uint8Array|ArrayBuffer): input data to decompress.
* - options (Object): zlib inflate options.
*
* Just shortcut to [[inflate]], because it autodetects format
* by header.content. Done for convenience.
**/
module.exports.Inflate = Inflate;
module.exports.inflate = inflate;
module.exports.inflateRaw = inflateRaw;
module.exports.ungzip = inflate;
module.exports.constants = require('./zlib/constants');

137
src/utils/buffs.ts Normal file
View file

@ -0,0 +1,137 @@
type StaticMembers<D> = {
length: number;
buf: buffer;
set(this: TypedArray<D>, array: TypedArray<D>, offset?: number): void;
subarray(this: TypedArray<D>, start: number, end?: number): TypedArray<D>;
zeroize(this: TypedArray<D>): void;
_startOffset?: number;
};
export type TypedArray<D> = {
[index: number]: number;
} & StaticMembers<D> & {
__nominal_TypedArray: D;
};
interface TypedArrayConstructor<D> {
new (len: number): TypedArray<D>;
new (nums: number[]): TypedArray<D>;
from(buf: buffer): TypedArray<D>;
BYTES_PER_ELEMENT: number;
}
const makeTypedArray = <D extends number>({
bytesPerElement,
read,
write,
}: {
bytesPerElement: 1 | 2 | 4;
read: (buf: buffer, offset: number) => number;
write: (buf: buffer, offset: number, value: number) => void;
}) => {
const metatable: LuaMetatable<StaticMembers<D>> = {
__index: (me, index) => {
assert(typeIs(index, "number"), "index must be a number");
read(me.buf, index * bytesPerElement);
},
__newindex: (me, index, value) => {
assert(typeIs(index, "number"), "index must be a number");
assert(typeIs(value, "number"), "value must be a number");
write(me.buf, index * bytesPerElement, value);
},
__tostring: (me) => {
return buffer.tostring(me.buf);
},
};
function _make(buf: buffer): TypedArray<D> {
return setmetatable(
{
buf,
length: buffer.len(buf) / bytesPerElement,
set(this: TypedArray<D>, array: TypedArray<D>, offset = 0) {
buffer.copy(this.buf, offset * bytesPerElement, array.buf);
},
subarray(this: TypedArray<D>, start: number, finish: number = this.length) {
const len = finish - start;
const newBuf = buffer.create(len * bytesPerElement);
buffer.copy(newBuf, 0, this.buf, start * bytesPerElement, len);
return _make(newBuf);
},
zeroize(this: TypedArray<D>) {
buffer.fill(this.buf, 0, 0);
},
} satisfies StaticMembers<D>,
metatable,
) as unknown as TypedArray<D>;
}
return class TypedArray {
constructor(nums: number | number[]) {
if (typeIs(nums, "number")) {
return _make(buffer.create(nums * bytesPerElement));
}
const buf = buffer.create(nums.size() * bytesPerElement);
let offset = 0;
for (const n of nums) {
write(buf, offset, n);
offset += bytesPerElement;
}
return _make(buf);
}
static from(buf: buffer) {
return _make(buf);
}
static BYTES_PER_ELEMENT = bytesPerElement;
} as unknown as TypedArrayConstructor<D>;
};
export const Uint8Array = makeTypedArray<-1>({
bytesPerElement: 1,
read: buffer.readu8,
write: buffer.writeu8,
});
export type Uint8Array = InstanceType<typeof Uint8Array>;
export const Uint16Array = makeTypedArray<-2>({
bytesPerElement: 2,
read: buffer.readu16,
write: buffer.writeu16,
});
export type Uint16Array = InstanceType<typeof Uint16Array>;
export const Uint32Array = makeTypedArray<-4>({
bytesPerElement: 4,
read: buffer.readu32,
write: buffer.writeu32,
});
export type Uint32Array = InstanceType<typeof Uint32Array>;
export const Int8Array = makeTypedArray<1>({
bytesPerElement: 1,
read: buffer.readi8,
write: buffer.writei8,
});
export type Int8Array = InstanceType<typeof Int8Array>;
export const Int16Array = makeTypedArray<2>({
bytesPerElement: 2,
read: buffer.readi16,
write: buffer.writei16,
});
export type Int16Array = InstanceType<typeof Int16Array>;
export const Int32Array = makeTypedArray<4>({
bytesPerElement: 4,
read: buffer.readi32,
write: buffer.writei32,
});
export type Int32Array = InstanceType<typeof Int32Array>;
export type NumericArrayLike = {
[index: number]: number;
};

View file

@ -1,48 +1,29 @@
'use strict'; export function assign<T extends Record<keyof any, any>>(obj: T, ...sources: Partial<T>[]): T {
for (const source of sources) {
if (!typeIs(source, "table")) {
error(source + "must be non-object");
}
for (const [k, v] of pairs(source)) {
obj[k as keyof typeof obj] = v as T[keyof T];
}
}
const _has = (obj, key) => { return obj;
return Object.prototype.hasOwnProperty.call(obj, key); }
};
module.exports.assign = function (obj /*from1, from2, from3, ...*/) { export function flattenChunks(chunks: buffer[]): buffer {
const sources = Array.prototype.slice.call(arguments, 1); // calculate data length
while (sources.length) { const len = chunks.reduce((acc, chunk) => acc + buffer.len(chunk), 0);
const source = sources.shift();
if (!source) { continue; }
if (typeof source !== 'object') { // join chunks
throw new TypeError(source + 'must be non-object'); const result = buffer.create(len);
} let offset = 0;
for (const p in source) { for (const chunk of chunks) {
if (_has(source, p)) { buffer.copy(result, offset, chunk);
obj[p] = source[p]; offset += buffer.len(chunk);
} }
}
}
return obj; return result;
}; }
// Join array of chunks to single array.
module.exports.flattenChunks = (chunks) => {
// calculate data length
let len = 0;
for (let i = 0, l = chunks.length; i < l; i++) {
len += chunks[i].length;
}
// join chunks
const result = new Uint8Array(len);
for (let i = 0, pos = 0, l = chunks.length; i < l; i++) {
let chunk = chunks[i];
result.set(chunk, pos);
pos += chunk.length;
}
return result;
};

View file

@ -1,174 +0,0 @@
// String encode/decode helpers
'use strict';
// Quick check if we can use fast array to bin string conversion
//
// - apply(Array) can fail on Android 2.2
// - apply(Uint8Array) can fail on iOS 5.1 Safari
//
let STR_APPLY_UIA_OK = true;
try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }
// Table with utf8 lengths (calculated by first byte of sequence)
// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,
// because max possible codepoint is 0x10ffff
const _utf8len = new Uint8Array(256);
for (let q = 0; q < 256; q++) {
_utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);
}
_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start
// convert string to array (typed, when possible)
module.exports.string2buf = (str) => {
if (typeof TextEncoder === 'function' && TextEncoder.prototype.encode) {
return new TextEncoder().encode(str);
}
let buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;
// count binary size
for (m_pos = 0; m_pos < str_len; m_pos++) {
c = str.charCodeAt(m_pos);
if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
c2 = str.charCodeAt(m_pos + 1);
if ((c2 & 0xfc00) === 0xdc00) {
c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
m_pos++;
}
}
buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;
}
// allocate buffer
buf = new Uint8Array(buf_len);
// convert
for (i = 0, m_pos = 0; i < buf_len; m_pos++) {
c = str.charCodeAt(m_pos);
if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {
c2 = str.charCodeAt(m_pos + 1);
if ((c2 & 0xfc00) === 0xdc00) {
c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);
m_pos++;
}
}
if (c < 0x80) {
/* one byte */
buf[i++] = c;
} else if (c < 0x800) {
/* two bytes */
buf[i++] = 0xC0 | (c >>> 6);
buf[i++] = 0x80 | (c & 0x3f);
} else if (c < 0x10000) {
/* three bytes */
buf[i++] = 0xE0 | (c >>> 12);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
} else {
/* four bytes */
buf[i++] = 0xf0 | (c >>> 18);
buf[i++] = 0x80 | (c >>> 12 & 0x3f);
buf[i++] = 0x80 | (c >>> 6 & 0x3f);
buf[i++] = 0x80 | (c & 0x3f);
}
}
return buf;
};
// Helper
const buf2binstring = (buf, len) => {
// On Chrome, the arguments in a function call that are allowed is `65534`.
// If the length of the buffer is smaller than that, we can use this optimization,
// otherwise we will take a slower path.
if (len < 65534) {
if (buf.subarray && STR_APPLY_UIA_OK) {
return String.fromCharCode.apply(null, buf.length === len ? buf : buf.subarray(0, len));
}
}
let result = '';
for (let i = 0; i < len; i++) {
result += String.fromCharCode(buf[i]);
}
return result;
};
// convert array to string
module.exports.buf2string = (buf, max) => {
const len = max || buf.length;
if (typeof TextDecoder === 'function' && TextDecoder.prototype.decode) {
return new TextDecoder().decode(buf.subarray(0, max));
}
let i, out;
// Reserve max possible length (2 words per char)
// NB: by unknown reasons, Array is significantly faster for
// String.fromCharCode.apply than Uint16Array.
const utf16buf = new Array(len * 2);
for (out = 0, i = 0; i < len;) {
let c = buf[i++];
// quick process ascii
if (c < 0x80) { utf16buf[out++] = c; continue; }
let c_len = _utf8len[c];
// skip 5 & 6 byte codes
if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }
// apply mask on first byte
c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;
// join the rest
while (c_len > 1 && i < len) {
c = (c << 6) | (buf[i++] & 0x3f);
c_len--;
}
// terminated by end of string?
if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }
if (c < 0x10000) {
utf16buf[out++] = c;
} else {
c -= 0x10000;
utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);
utf16buf[out++] = 0xdc00 | (c & 0x3ff);
}
}
return buf2binstring(utf16buf, out);
};
// Calculate max possible position in utf8 buffer,
// that will not break sequence. If that's not possible
// - (very small limits) return max size as is.
//
// buf[] - utf8 bytes array
// max - length limit (mandatory);
module.exports.utf8border = (buf, max) => {
max = max || buf.length;
if (max > buf.length) { max = buf.length; }
// go back from last position, until start of sequence found
let pos = max - 1;
while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }
// Very small and broken sequence,
// return max, because we should return something anyway.
if (pos < 0) { return max; }
// If we came to start of buffer - that means buffer is too small,
// return max too.
if (pos === 0) { return max; }
return (pos + _utf8len[buf[pos]] > max) ? pos : max;
};

View file

@ -1,4 +1,6 @@
'use strict'; "use strict";
import { NumericArrayLike } from "../utils/buffs";
// Note: adler32 takes 12% for level 0 and 2% for level 6. // Note: adler32 takes 12% for level 0 and 2% for level 6.
// It isn't worth it to make additional optimizations as in original. // It isn't worth it to make additional optimizations as in original.
@ -23,29 +25,26 @@
// misrepresented as being the original software. // misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
const adler32 = (adler, buf, len, pos) => { export const adler32 = (adler: number, buf: NumericArrayLike, len: number, pos: number) => {
let s1 = (adler & 0xffff) |0, let s1 = (adler & 0xffff) | 0,
s2 = ((adler >>> 16) & 0xffff) |0, s2 = ((adler >>> 16) & 0xffff) | 0,
n = 0; n = 0;
while (len !== 0) { while (len !== 0) {
// Set limit ~ twice less than 5552, to keep // Set limit ~ twice less than 5552, to keep
// s2 in 31-bits, because we force signed ints. // s2 in 31-bits, because we force signed ints.
// in other case %= will fail. // in other case %= will fail.
n = len > 2000 ? 2000 : len; n = len > 2000 ? 2000 : len;
len -= n; len -= n;
do { do {
s1 = (s1 + buf[pos++]) |0; s1 = (s1 + buf[pos++]) | 0;
s2 = (s2 + s1) |0; s2 = (s2 + s1) | 0;
} while (--n); } while (--n);
s1 %= 65521; s1 %= 65521;
s2 %= 65521; s2 %= 65521;
} }
return (s1 | (s2 << 16)) |0; return s1 | (s2 << 16) | 0;
}; };
module.exports = adler32;

View file

@ -1,4 +1,4 @@
'use strict'; "use strict";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -19,50 +19,46 @@
// misrepresented as being the original software. // misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
module.exports = { /* Allowed flush values; see deflate() and inflate() below for details */
export const Z_NO_FLUSH = 0;
export const Z_PARTIAL_FLUSH = 1;
export const Z_SYNC_FLUSH = 2;
export const Z_FULL_FLUSH = 3;
export const Z_FINISH = 4;
export const Z_BLOCK = 5;
export const Z_TREES = 6;
/* Allowed flush values; see deflate() and inflate() below for details */ /* Return codes for the compression/decompression functions. Negative values
Z_NO_FLUSH: 0, * are errors, positive values are used for special but normal events.
Z_PARTIAL_FLUSH: 1, */
Z_SYNC_FLUSH: 2, export const Z_OK = 0;
Z_FULL_FLUSH: 3, export const Z_STREAM_END = 1;
Z_FINISH: 4, export const Z_NEED_DICT = 2;
Z_BLOCK: 5, export const Z_ERRNO = -1;
Z_TREES: 6, export const Z_STREAM_ERROR = -2;
export const Z_DATA_ERROR = -3;
export const Z_MEM_ERROR = -4;
export const Z_BUF_ERROR = -5;
//Z_VERSION_ERROR: -6,
/* Return codes for the compression/decompression functions. Negative values /* compression levels */
* are errors, positive values are used for special but normal events. export const Z_NO_COMPRESSION = 0;
*/ export const Z_BEST_SPEED = 1;
Z_OK: 0, export const Z_BEST_COMPRESSION = 9;
Z_STREAM_END: 1, export const Z_DEFAULT_COMPRESSION = -1;
Z_NEED_DICT: 2,
Z_ERRNO: -1,
Z_STREAM_ERROR: -2,
Z_DATA_ERROR: -3,
Z_MEM_ERROR: -4,
Z_BUF_ERROR: -5,
//Z_VERSION_ERROR: -6,
/* compression levels */ export const Z_FILTERED = 1;
Z_NO_COMPRESSION: 0, export const Z_HUFFMAN_ONLY = 2;
Z_BEST_SPEED: 1, export const Z_RLE = 3;
Z_BEST_COMPRESSION: 9, export const Z_FIXED = 4;
Z_DEFAULT_COMPRESSION: -1, export const Z_DEFAULT_STRATEGY = 0;
/* Possible values of the data_type field (though see inflate()) */
export const Z_BINARY = 0;
export const Z_TEXT = 1;
//Z_ASCII: 1, // = Z_TEXT (deprecated)
export const Z_UNKNOWN = 2;
Z_FILTERED: 1, /* The deflate compression method */
Z_HUFFMAN_ONLY: 2, export const Z_DEFLATED = 8;
Z_RLE: 3, //Z_NULL: null // Use -1 or null inline, depending on var type
Z_FIXED: 4,
Z_DEFAULT_STRATEGY: 0,
/* Possible values of the data_type field (though see inflate()) */
Z_BINARY: 0,
Z_TEXT: 1,
//Z_ASCII: 1, // = Z_TEXT (deprecated)
Z_UNKNOWN: 2,
/* The deflate compression method */
Z_DEFLATED: 8
//Z_NULL: null // Use -1 or null inline, depending on var type
};

View file

@ -1,4 +1,6 @@
'use strict'; "use strict";
import { NumericArrayLike, Uint32Array } from "../utils/buffs";
// Note: we can't get significant speed boost here. // Note: we can't get significant speed boost here.
// So write code to minimize size - no pregenerated tables // So write code to minimize size - no pregenerated tables
@ -25,35 +27,31 @@
// Use ordinary array, since untyped makes no boost here // Use ordinary array, since untyped makes no boost here
const makeTable = () => { const makeTable = () => {
let c, table = []; let c;
const tbl = [];
for (var n = 0; n < 256; n++) { for (let n = 0; n < 256; n++) {
c = n; c = n;
for (var k = 0; k < 8; k++) { for (let k = 0; k < 8; k++) {
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
} }
table[n] = c; tbl[n] = c;
} }
return table; return tbl;
}; };
// Create table on load. Just 255 signed longs. Not a problem. // Create table on load. Just 255 signed longs. Not a problem.
const crcTable = new Uint32Array(makeTable()); const crcTable = new Uint32Array(makeTable());
export function crc32(crc: number, buf: NumericArrayLike, len: number, pos: number) {
const finish = pos + len;
const crc32 = (crc, buf, len, pos) => { crc ^= -1;
const t = crcTable;
const end = pos + len;
crc ^= -1; for (let i = pos; i < finish; i++) {
crc = (crc >>> 8) ^ crcTable[(crc ^ buf[i]) & 0xff];
}
for (let i = pos; i < end; i++) { return crc ^ -1; // >>> 0;
crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; }
}
return (crc ^ (-1)); // >>> 0;
};
module.exports = crc32;

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,6 @@
'use strict'; "use strict";
import { Uint8Array } from "../utils/buffs";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -19,40 +21,38 @@
// misrepresented as being the original software. // misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
function GZheader() { export class GZheader {
/* true if compressed data believed to be text */ /* true if compressed data believed to be text */
this.text = 0; public text = 0;
/* modification time */ /* modification time */
this.time = 0; public time = 0;
/* extra flags (not used when writing a gzip file) */ /* extra flags (not used when writing a gzip file) */
this.xflags = 0; public xflags = 0;
/* operating system */ /* operating system */
this.os = 0; public os = 0;
/* pointer to extra field or Z_NULL if none */ /* pointer to extra field or Z_NULL if none */
this.extra = null; public extra?: Uint8Array;
/* extra field length (valid if extra != Z_NULL) */ /* extra field length (valid if extra != Z_NULL) */
this.extra_len = 0; // Actually, we don't need it in JS, public extra_len = 0; // Actually, we don't need it in JS,
// but leave for few code modifications // but leave for few code modifications
// //
// Setup limits is not necessary because in js we should not preallocate memory // Setup limits is not necessary because in js we should not preallocate memory
// for inflate use constant limit in 65536 bytes // for inflate use constant limit in 65536 bytes
// //
/* space at extra (only when reading header) */ /* space at extra (only when reading header) */
// this.extra_max = 0; // public extra_max = 0;
/* pointer to zero-terminated file name or Z_NULL */ /* pointer to zero-terminated file name or Z_NULL */
this.name = ''; public name = "";
/* space at name (only when reading header) */ /* space at name (only when reading header) */
// this.name_max = 0; // public name_max = 0;
/* pointer to zero-terminated comment or Z_NULL */ /* pointer to zero-terminated comment or Z_NULL */
this.comment = ''; public comment = "";
/* space at comment (only when reading header) */ /* space at comment (only when reading header) */
// this.comm_max = 0; // public comm_max = 0;
/* true if there was or will be a header crc */ /* true if there was or will be a header crc */
this.hcrc = 0; public hcrc = 0;
/* true when done reading gzip header (not used when writing a gzip file) */ /* true when done reading gzip header (not used when writing a gzip file) */
this.done = false; public done = false;
} }
module.exports = GZheader;

View file

@ -1,4 +1,7 @@
'use strict'; "use strict";
import { InflateState } from "./inflate";
import { ZStream } from "./zstream";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -20,8 +23,8 @@
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
// See state defs from inflate.js // See state defs from inflate.js
const BAD = 16209; /* got a data error -- remain here until reset */ const BAD = 16209; /* got a data error -- remain here until reset */
const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */ const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */
/* /*
Decode literal, length, and distance codes and write out the resulting Decode literal, length, and distance codes and write out the resulting
@ -58,287 +61,302 @@ const TYPE = 16191; /* i: waiting for type bits, including last-flag bit */
requires strm.avail_out >= 258 for each loop to avoid checking for requires strm.avail_out >= 258 for each loop to avoid checking for
output space. output space.
*/ */
module.exports = function inflate_fast(strm, start) { export function inflate_fast(strm: ZStream<InflateState>, start: number) {
let _in; /* local strm.input */ let _in; /* local strm.input */
let last; /* have enough input while in < last */ let last; /* have enough input while in < last */
let _out; /* local strm.output */ let _out; /* local strm.output */
let beg; /* inflate()'s initial strm.output */ let beg; /* inflate()'s initial strm.output */
let end; /* while out < end, enough space available */ let finish; /* while out < end, enough space available */
//#ifdef INFLATE_STRICT //#ifdef INFLATE_STRICT
let dmax; /* maximum distance from zlib header */ let dmax; /* maximum distance from zlib header */
//#endif //#endif
let wsize; /* window size or zero if not using window */ let wsize; /* window size or zero if not using window */
let whave; /* valid bytes in the window */ let whave; /* valid bytes in the window */
let wnext; /* window write index */ let wnext; /* window write index */
// Use `s_window` instead `window`, avoid conflict with instrumentation tools // Use `s_window` instead `window`, avoid conflict with instrumentation tools
let s_window; /* allocated sliding window, if wsize != 0 */ let s_window; /* allocated sliding window, if wsize != 0 */
let hold; /* local strm.hold */ let hold; /* local strm.hold */
let bits; /* local strm.bits */ let bits; /* local strm.bits */
let lcode; /* local strm.lencode */ let lcode; /* local strm.lencode */
let dcode; /* local strm.distcode */ let dcode; /* local strm.distcode */
let lmask; /* mask for first level of length codes */ let lmask; /* mask for first level of length codes */
let dmask; /* mask for first level of distance codes */ let dmask; /* mask for first level of distance codes */
let here; /* retrieved table entry */ let here; /* retrieved table entry */
let op; /* code bits, operation, extra bits, or */ let op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */ /* window position, window bytes to copy */
let len; /* match length, unused bytes */ let len; /* match length, unused bytes */
let dist; /* match distance */ let dist; /* match distance */
let from; /* where to copy match from */ let from; /* where to copy match from */
let from_source; let from_source;
let input, output; // JS specific, because we have no pointers
let input, output; // JS specific, because we have no pointers /* copy state to local variables */
const state = strm.state;
//here = state.here;
_in = strm.next_in;
input = strm.input;
last = _in + (strm.avail_in - 5);
_out = strm.next_out;
output = strm.output;
beg = _out - (start - strm.avail_out);
finish = _out + (strm.avail_out - 257);
//#ifdef INFLATE_STRICT
dmax = state.dmax;
//#endif
wsize = state.wsize;
whave = state.whave;
wnext = state.wnext;
s_window = state.window;
hold = state.hold;
bits = state.bits;
lcode = state.lencode;
dcode = state.distcode;
lmask = (1 << state.lenbits) - 1;
dmask = (1 << state.distbits) - 1;
/* copy state to local variables */ /* decode literals and length/distances until end-of-block or not enough
const state = strm.state;
//here = state.here;
_in = strm.next_in;
input = strm.input;
last = _in + (strm.avail_in - 5);
_out = strm.next_out;
output = strm.output;
beg = _out - (start - strm.avail_out);
end = _out + (strm.avail_out - 257);
//#ifdef INFLATE_STRICT
dmax = state.dmax;
//#endif
wsize = state.wsize;
whave = state.whave;
wnext = state.wnext;
s_window = state.window;
hold = state.hold;
bits = state.bits;
lcode = state.lencode;
dcode = state.distcode;
lmask = (1 << state.lenbits) - 1;
dmask = (1 << state.distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */ input data or output space */
top: let break_top = false;
do {
if (bits < 15) {
hold += input[_in++] << bits;
bits += 8;
hold += input[_in++] << bits;
bits += 8;
}
here = lcode[hold & lmask]; do {
if (break_top) {
break;
}
dolen: if (bits < 15) {
for (;;) { // Goto emulation hold += input[_in++] << bits;
op = here >>> 24/*here.bits*/; bits += 8;
hold >>>= op; hold += input[_in++] << bits;
bits -= op; bits += 8;
op = (here >>> 16) & 0xff/*here.op*/; }
if (op === 0) { /* literal */
//Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
// "inflate: literal '%c'\n" :
// "inflate: literal 0x%02x\n", here.val));
output[_out++] = here & 0xffff/*here.val*/;
}
else if (op & 16) { /* length base */
len = here & 0xffff/*here.val*/;
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
hold += input[_in++] << bits;
bits += 8;
}
len += hold & ((1 << op) - 1);
hold >>>= op;
bits -= op;
}
//Tracevv((stderr, "inflate: length %u\n", len));
if (bits < 15) {
hold += input[_in++] << bits;
bits += 8;
hold += input[_in++] << bits;
bits += 8;
}
here = dcode[hold & dmask];
dodist: here = lcode[hold & lmask];
for (;;) { // goto emulation
op = here >>> 24/*here.bits*/;
hold >>>= op;
bits -= op;
op = (here >>> 16) & 0xff/*here.op*/;
if (op & 16) { /* distance base */ for (;;) {
dist = here & 0xffff/*here.val*/; if (break_top) {
op &= 15; /* number of extra bits */ break;
if (bits < op) { }
hold += input[_in++] << bits;
bits += 8;
if (bits < op) {
hold += input[_in++] << bits;
bits += 8;
}
}
dist += hold & ((1 << op) - 1);
//#ifdef INFLATE_STRICT
if (dist > dmax) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break top;
}
//#endif
hold >>>= op;
bits -= op;
//Tracevv((stderr, "inflate: distance %u\n", dist));
op = _out - beg; /* max distance in output */
if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state.sane) {
strm.msg = 'invalid distance too far back';
state.mode = BAD;
break top;
}
// (!) This block is disabled in zlib defaults, // Goto emulation
// don't enable it for binary compatibility op = here >>> 24 /*here.bits*/;
//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR hold >>>= op;
// if (len <= op - whave) { bits -= op;
// do { op = (here >>> 16) & 0xff /*here.op*/;
// output[_out++] = 0; if (op === 0) {
// } while (--len); /* literal */
// continue top; //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
// } // "inflate: literal '%c'\n" :
// len -= op - whave; // "inflate: literal 0x%02x\n", here.val));
// do { output[_out++] = here & 0xffff /*here.val*/;
// output[_out++] = 0; } else if (op & 16) {
// } while (--op > whave); /* length base */
// if (op === 0) { len = here & 0xffff /*here.val*/;
// from = _out - dist; op &= 15; /* number of extra bits */
// do { if (op) {
// output[_out++] = output[from++]; if (bits < op) {
// } while (--len); hold += input[_in++] << bits;
// continue top; bits += 8;
// } }
//#endif len += hold & ((1 << op) - 1);
} hold >>>= op;
from = 0; // window index bits -= op;
from_source = s_window; }
if (wnext === 0) { /* very common case */ //Tracevv((stderr, "inflate: length %u\n", len));
from += wsize - op; if (bits < 15) {
if (op < len) { /* some from window */ hold += input[_in++] << bits;
len -= op; bits += 8;
do { hold += input[_in++] << bits;
output[_out++] = s_window[from++]; bits += 8;
} while (--op); }
from = _out - dist; /* rest from output */ here = dcode[hold & dmask];
from_source = output;
}
}
else if (wnext < op) { /* wrap around window */
from += wsize + wnext - op;
op -= wnext;
if (op < len) { /* some from end of window */
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = 0;
if (wnext < len) { /* some from start of window */
op = wnext;
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = _out - dist; /* rest from output */
from_source = output;
}
}
}
else { /* contiguous in window */
from += wnext - op;
if (op < len) { /* some from window */
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = _out - dist; /* rest from output */
from_source = output;
}
}
while (len > 2) {
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
len -= 3;
}
if (len) {
output[_out++] = from_source[from++];
if (len > 1) {
output[_out++] = from_source[from++];
}
}
}
else {
from = _out - dist; /* copy direct from output */
do { /* minimum length is three */
output[_out++] = output[from++];
output[_out++] = output[from++];
output[_out++] = output[from++];
len -= 3;
} while (len > 2);
if (len) {
output[_out++] = output[from++];
if (len > 1) {
output[_out++] = output[from++];
}
}
}
}
else if ((op & 64) === 0) { /* 2nd level distance code */
here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];
continue dodist;
}
else {
strm.msg = 'invalid distance code';
state.mode = BAD;
break top;
}
break; // need to emulate goto via "continue" for (;;) {
} // goto emulation
} op = here >>> 24 /*here.bits*/;
else if ((op & 64) === 0) { /* 2nd level length code */ hold >>>= op;
here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; bits -= op;
continue dolen; op = (here >>> 16) & 0xff /*here.op*/;
}
else if (op & 32) { /* end-of-block */
//Tracevv((stderr, "inflate: end of block\n"));
state.mode = TYPE;
break top;
}
else {
strm.msg = 'invalid literal/length code';
state.mode = BAD;
break top;
}
break; // need to emulate goto via "continue" if (op & 16) {
} /* distance base */
} while (_in < last && _out < end); dist = here & 0xffff /*here.val*/;
op &= 15; /* number of extra bits */
if (bits < op) {
hold += input[_in++] << bits;
bits += 8;
if (bits < op) {
hold += input[_in++] << bits;
bits += 8;
}
}
dist += hold & ((1 << op) - 1);
//#ifdef INFLATE_STRICT
if (dist > dmax) {
strm.msg = "invalid distance too far back";
state.mode = BAD;
break_top = true;
break;
}
//#endif
hold >>>= op;
bits -= op;
//Tracevv((stderr, "inflate: distance %u\n", dist));
op = _out - beg; /* max distance in output */
if (dist > op) {
/* see if copy from window */
op = dist - op; /* distance back in window */
if (op > whave) {
if (state.sane) {
strm.msg = "invalid distance too far back";
state.mode = BAD;
break_top = true;
break;
}
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */ // (!) This block is disabled in zlib defaults,
len = bits >> 3; // don't enable it for binary compatibility
_in -= len; //#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
bits -= len << 3; // if (len <= op - whave) {
hold &= (1 << bits) - 1; // do {
// output[_out++] = 0;
// } while (--len);
// continue top;
// }
// len -= op - whave;
// do {
// output[_out++] = 0;
// } while (--op > whave);
// if (op === 0) {
// from = _out - dist;
// do {
// output[_out++] = output[from++];
// } while (--len);
// continue top;
// }
//#endif
}
from = 0; // window index
from_source = s_window;
if (wnext === 0) {
/* very common case */
from += wsize - op;
if (op < len) {
/* some from window */
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = _out - dist; /* rest from output */
from_source = output;
}
} else if (wnext < op) {
/* wrap around window */
from += wsize + wnext - op;
op -= wnext;
if (op < len) {
/* some from end of window */
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = 0;
if (wnext < len) {
/* some from start of window */
op = wnext;
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = _out - dist; /* rest from output */
from_source = output;
}
}
} else {
/* contiguous in window */
from += wnext - op;
if (op < len) {
/* some from window */
len -= op;
do {
output[_out++] = s_window[from++];
} while (--op);
from = _out - dist; /* rest from output */
from_source = output;
}
}
while (len > 2) {
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
output[_out++] = from_source[from++];
len -= 3;
}
if (len) {
output[_out++] = from_source[from++];
if (len > 1) {
output[_out++] = from_source[from++];
}
}
} else {
from = _out - dist; /* copy direct from output */
do {
/* minimum length is three */
output[_out++] = output[from++];
output[_out++] = output[from++];
output[_out++] = output[from++];
len -= 3;
} while (len > 2);
if (len) {
output[_out++] = output[from++];
if (len > 1) {
output[_out++] = output[from++];
}
}
}
} else if ((op & 64) === 0) {
/* 2nd level distance code */
here = dcode[(here & 0xffff) /*here.val*/ + (hold & ((1 << op) - 1))];
continue;
} else {
strm.msg = "invalid distance code";
state.mode = BAD;
break_top = true;
}
/* update state and return */ break; // need to emulate goto via "continue"
strm.next_in = _in; }
strm.next_out = _out; } else if ((op & 64) === 0) {
strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); /* 2nd level length code */
strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); here = lcode[(here & 0xffff) /*here.val*/ + (hold & ((1 << op) - 1))];
state.hold = hold; continue;
state.bits = bits; } else if (op & 32) {
return; /* end-of-block */
}; //Tracevv((stderr, "inflate: end of block\n"));
state.mode = TYPE;
break_top = true;
} else {
strm.msg = "invalid literal/length code";
state.mode = BAD;
break_top = true;
}
break; // need to emulate goto via "continue"
}
} while (_in < last && _out < finish);
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
len = bits >> 3;
_in -= len;
bits -= len << 3;
hold &= (1 << bits) - 1;
/* update state and return */
strm.next_in = _in;
strm.next_out = _out;
strm.avail_in = _in < last ? 5 + (last - _in) : 5 - (_in - last);
strm.avail_out = _out < finish ? 257 + (finish - _out) : 257 - (_out - finish);
state.hold = hold;
state.bits = bits;
return;
}

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,6 @@
'use strict'; "use strict";
import { NumericArrayLike, Uint16Array, Uint8Array } from "../utils/buffs";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -28,57 +30,64 @@ const CODES = 0;
const LENS = 1; const LENS = 1;
const DISTS = 2; const DISTS = 2;
const lbase = new Uint16Array([ /* Length codes 257..285 base */ const lbase = new Uint16Array([
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 99, 115, 131, 163, 195, 227, 258, 0, 0,
]); ]);
const lext = new Uint8Array([ /* Length codes 257..285 extra */ const lext = new Uint8Array([
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78,
]); ]);
const dbase = new Uint16Array([ /* Distance codes 0..29 base */ const dbase = new Uint16Array([
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0,
8193, 12289, 16385, 24577, 0, 0
]); ]);
const dext = new Uint8Array([ /* Distance codes 0..29 extra */ const dext = new Uint8Array([
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, /* Distance codes 0..29 extra */ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64,
28, 28, 29, 29, 64, 64
]); ]);
const inflate_table = (type, lens, lens_index, codes, table, table_index, work, opts) => export const inflate_table = (
{ ty: number,
const bits = opts.bits; lens: NumericArrayLike,
//here = opts.here; /* table entry for duplication */ lens_index: number,
codes: number,
tbl: NumericArrayLike,
table_index: number,
work: NumericArrayLike,
opts: { bits: number },
) => {
const bits = opts.bits;
//here = opts.here; /* table entry for duplication */
let len = 0; /* a code's length in bits */ let len = 0; /* a code's length in bits */
let sym = 0; /* index of code symbols */ let sym = 0; /* index of code symbols */
let min = 0, max = 0; /* minimum and maximum code lengths */ let min = 0,
let root = 0; /* number of index bits for root table */ max = 0; /* minimum and maximum code lengths */
let curr = 0; /* number of index bits for current table */ let root = 0; /* number of index bits for root table */
let drop = 0; /* code bits to drop for sub-table */ let curr = 0; /* number of index bits for current table */
let left = 0; /* number of prefix codes available */ let drop = 0; /* code bits to drop for sub-table */
let used = 0; /* code entries in table used */ let left = 0; /* number of prefix codes available */
let huff = 0; /* Huffman code */ let used = 0; /* code entries in table used */
let incr; /* for incrementing code, index */ let huff = 0; /* Huffman code */
let fill; /* index for replicating entries */ let incr; /* for incrementing code, index */
let low; /* low bits for current root entry */ let fill; /* index for replicating entries */
let mask; /* mask for low root bits */ let low; /* low bits for current root entry */
let next; /* next available space in table */ let mask; /* mask for low root bits */
let base = null; /* base value table to use */ let next_space; /* next available space in table */
// let shoextra; /* extra bits table to use */ let base; /* base value table to use */
let match; /* use base and extra for symbol >= match */ // let shoextra; /* extra bits table to use */
const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ let match; /* use base and extra for symbol >= match */
const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ const count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */
let extra = null; const offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */
let extra;
let here_bits, here_op, here_val; let here_bits, here_op, here_val;
/* /*
Process a set of code lengths to create a canonical Huffman code. The Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the symbols 0..codes-1. The Huffman code is generated by first sorting the
@ -109,71 +118,75 @@ const inflate_table = (type, lens, lens_index, codes, table, table_index, work,
decoding tables. decoding tables.
*/ */
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++) { for (len = 0; len <= MAXBITS; len++) {
count[len] = 0; count[len] = 0;
} }
for (sym = 0; sym < codes; sym++) { for (sym = 0; sym < codes; sym++) {
count[lens[lens_index + sym]]++; count[lens[lens_index + sym]]++;
} }
/* bound code lengths, force root to be within code lengths */ /* bound code lengths, force root to be within code lengths */
root = bits; root = bits;
for (max = MAXBITS; max >= 1; max--) { for (max = MAXBITS; max >= 1; max--) {
if (count[max] !== 0) { break; } if (count[max] !== 0) {
} break;
if (root > max) { }
root = max; }
} if (root > max) {
if (max === 0) { /* no symbols to code at all */ root = max;
//table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ }
//table.bits[opts.table_index] = 1; //here.bits = (var char)1; if (max === 0) {
//table.val[opts.table_index++] = 0; //here.val = (var short)0; /* no symbols to code at all */
table[table_index++] = (1 << 24) | (64 << 16) | 0; //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */
//table.bits[opts.table_index] = 1; //here.bits = (var char)1;
//table.val[opts.table_index++] = 0; //here.val = (var short)0;
tbl[table_index++] = (1 << 24) | (64 << 16) | 0;
//table.op[opts.table_index] = 64;
//table.bits[opts.table_index] = 1;
//table.val[opts.table_index++] = 0;
tbl[table_index++] = (1 << 24) | (64 << 16) | 0;
//table.op[opts.table_index] = 64; opts.bits = 1;
//table.bits[opts.table_index] = 1; return 0; /* no symbols, but wait for decoding to report error */
//table.val[opts.table_index++] = 0; }
table[table_index++] = (1 << 24) | (64 << 16) | 0; for (min = 1; min < max; min++) {
if (count[min] !== 0) {
break;
}
}
if (root < min) {
root = min;
}
opts.bits = 1; /* check for an over-subscribed or incomplete set of lengths */
return 0; /* no symbols, but wait for decoding to report error */ left = 1;
} for (len = 1; len <= MAXBITS; len++) {
for (min = 1; min < max; min++) { left <<= 1;
if (count[min] !== 0) { break; } left -= count[len];
} if (left < 0) {
if (root < min) { return -1;
root = min; } /* over-subscribed */
} }
if (left > 0 && (ty === CODES || max !== 1)) {
return -1; /* incomplete set */
}
/* check for an over-subscribed or incomplete set of lengths */ /* generate offsets into symbol table for each length for sorting */
left = 1; offs[1] = 0;
for (len = 1; len <= MAXBITS; len++) { for (len = 1; len < MAXBITS; len++) {
left <<= 1; offs[len + 1] = offs[len] + count[len];
left -= count[len]; }
if (left < 0) {
return -1;
} /* over-subscribed */
}
if (left > 0 && (type === CODES || max !== 1)) {
return -1; /* incomplete set */
}
/* generate offsets into symbol table for each length for sorting */ /* sort symbols by length, by symbol order within each length */
offs[1] = 0; for (sym = 0; sym < codes; sym++) {
for (len = 1; len < MAXBITS; len++) { if (lens[lens_index + sym] !== 0) {
offs[len + 1] = offs[len] + count[len]; work[offs[lens[lens_index + sym]]++] = sym;
} }
}
/* sort symbols by length, by symbol order within each length */ /*
for (sym = 0; sym < codes; sym++) {
if (lens[lens_index + sym] !== 0) {
work[offs[lens[lens_index + sym]]++] = sym;
}
}
/*
Create and fill in decoding tables. In this loop, the table being Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop with length len. That code is converted to an index by dropping drop
@ -204,137 +217,133 @@ const inflate_table = (type, lens, lens_index, codes, table, table_index, work,
in the rest of the decoding tables with invalid code markers. in the rest of the decoding tables with invalid code markers.
*/ */
/* set up for code type */ /* set up for code type */
// poor man optimization - use if-else instead of switch, // poor man optimization - use if-else instead of switch,
// to avoid deopts in old v8 // to avoid deopts in old v8
if (type === CODES) { if (ty === CODES) {
base = extra = work; /* dummy value--not used */ base = extra = work; /* dummy value--not used */
match = 20; match = 20;
} else if (ty === LENS) {
base = lbase;
extra = lext;
match = 257;
} else {
/* DISTS */
base = dbase;
extra = dext;
match = 0;
}
} else if (type === LENS) { /* initialize opts for loop */
base = lbase; huff = 0; /* starting code */
extra = lext; sym = 0; /* starting code symbol */
match = 257; len = min; /* starting code length */
next_space = table_index; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = -1; /* trigger new sub-table when len > root */
used = 1 << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
} else { /* DISTS */ /* check available table space */
base = dbase; if ((ty === LENS && used > ENOUGH_LENS) || (ty === DISTS && used > ENOUGH_DISTS)) {
extra = dext; return 1;
match = 0; }
}
/* initialize opts for loop */ /* process all codes and make table entries */
huff = 0; /* starting code */ for (;;) {
sym = 0; /* starting code symbol */ /* create table entry */
len = min; /* starting code length */ here_bits = len - drop;
next = table_index; /* current table to fill in */ if (work[sym] + 1 < match) {
curr = root; /* current table index bits */ here_op = 0;
drop = 0; /* current bits to drop from code for index */ here_val = work[sym];
low = -1; /* trigger new sub-table when len > root */ } else if (work[sym] >= match) {
used = 1 << root; /* use root table entries */ here_op = extra[work[sym] - match];
mask = used - 1; /* mask for comparing low */ here_val = base[work[sym] - match];
} else {
here_op = 32 + 64; /* end of block */
here_val = 0;
}
/* check available table space */ /* replicate for those indices with low len bits equal to huff */
if ((type === LENS && used > ENOUGH_LENS) || incr = 1 << (len - drop);
(type === DISTS && used > ENOUGH_DISTS)) { fill = 1 << curr;
return 1; min = fill; /* save offset to next table */
} do {
fill -= incr;
tbl[next_space + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val | 0;
} while (fill !== 0);
/* process all codes and make table entries */ /* backwards increment the len-bit code huff */
for (;;) { incr = 1 << (len - 1);
/* create table entry */ while (huff & incr) {
here_bits = len - drop; incr >>= 1;
if (work[sym] + 1 < match) { }
here_op = 0; if (incr !== 0) {
here_val = work[sym]; huff &= incr - 1;
} huff += incr;
else if (work[sym] >= match) { } else {
here_op = extra[work[sym] - match]; huff = 0;
here_val = base[work[sym] - match]; }
}
else {
here_op = 32 + 64; /* end of block */
here_val = 0;
}
/* replicate for those indices with low len bits equal to huff */ /* go to next symbol, update count, len */
incr = 1 << (len - drop); sym++;
fill = 1 << curr; if (--count[len] === 0) {
min = fill; /* save offset to next table */ if (len === max) {
do { break;
fill -= incr; }
table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; len = lens[lens_index + work[sym]];
} while (fill !== 0); }
/* backwards increment the len-bit code huff */ /* create new sub-table if needed */
incr = 1 << (len - 1); if (len > root && (huff & mask) !== low) {
while (huff & incr) { /* if first time, transition to sub-tables */
incr >>= 1; if (drop === 0) {
} drop = root;
if (incr !== 0) { }
huff &= incr - 1;
huff += incr;
} else {
huff = 0;
}
/* go to next symbol, update count, len */ /* increment past last table */
sym++; next_space += min; /* here min is 1 << curr */
if (--count[len] === 0) {
if (len === max) { break; }
len = lens[lens_index + work[sym]];
}
/* create new sub-table if needed */ /* determine length of next table */
if (len > root && (huff & mask) !== low) { curr = len - drop;
/* if first time, transition to sub-tables */ left = 1 << curr;
if (drop === 0) { while (curr + drop < max) {
drop = root; left -= count[curr + drop];
} if (left <= 0) {
break;
}
curr++;
left <<= 1;
}
/* increment past last table */ /* check for enough space */
next += min; /* here min is 1 << curr */ used += 1 << curr;
if ((ty === LENS && used > ENOUGH_LENS) || (ty === DISTS && used > ENOUGH_DISTS)) {
return 1;
}
/* determine length of next table */ /* point entry in root table to sub-table */
curr = len - drop; low = huff & mask;
left = 1 << curr; /*table.op[low] = curr;
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) { break; }
curr++;
left <<= 1;
}
/* check for enough space */
used += 1 << curr;
if ((type === LENS && used > ENOUGH_LENS) ||
(type === DISTS && used > ENOUGH_DISTS)) {
return 1;
}
/* point entry in root table to sub-table */
low = huff & mask;
/*table.op[low] = curr;
table.bits[low] = root; table.bits[low] = root;
table.val[low] = next - opts.table_index;*/ table.val[low] = next - opts.table_index;*/
table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; tbl[low] = (root << 24) | (curr << 16) | (next_space - table_index) | 0;
} }
} }
/* fill in remaining table entry if code is incomplete (guaranteed to have /* fill in remaining table entry if code is incomplete (guaranteed to have
at most one remaining entry, since if the code is incomplete, the at most one remaining entry, since if the code is incomplete, the
maximum code length that was allowed to get this far is one bit) */ maximum code length that was allowed to get this far is one bit) */
if (huff !== 0) { if (huff !== 0) {
//table.op[next + huff] = 64; /* invalid code marker */ //table.op[next + huff] = 64; /* invalid code marker */
//table.bits[next + huff] = len - drop; //table.bits[next + huff] = len - drop;
//table.val[next + huff] = 0; //table.val[next + huff] = 0;
table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; tbl[next_space + huff] = ((len - drop) << 24) | (64 << 16) | 0;
} }
/* set return parameters */ /* set return parameters */
//opts.table_index += used; //opts.table_index += used;
opts.bits = root; opts.bits = root;
return 0; return 0;
}; };
module.exports = inflate_table;

View file

@ -1,4 +1,4 @@
'use strict'; "use strict";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -19,14 +19,14 @@
// misrepresented as being the original software. // misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
module.exports = { export default {
2: 'need dictionary', /* Z_NEED_DICT 2 */ 2: "need dictionary" /* Z_NEED_DICT 2 */,
1: 'stream end', /* Z_STREAM_END 1 */ 1: "stream end" /* Z_STREAM_END 1 */,
0: '', /* Z_OK 0 */ 0: "" /* Z_OK 0 */,
'-1': 'file error', /* Z_ERRNO (-1) */ [-1]: "file error" /* Z_ERRNO (-1) */,
'-2': 'stream error', /* Z_STREAM_ERROR (-2) */ [-2]: "stream error" /* Z_STREAM_ERROR (-2) */,
'-3': 'data error', /* Z_DATA_ERROR (-3) */ [-3]: "data error" /* Z_DATA_ERROR (-3) */,
'-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ [-4]: "insufficient memory" /* Z_MEM_ERROR (-4) */,
'-5': 'buffer error', /* Z_BUF_ERROR (-5) */ [-5]: "buffer error" /* Z_BUF_ERROR (-5) */,
'-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ [-6]: "incompatible version" /* Z_VERSION_ERROR (-6) */,
}; };

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,7 @@
'use strict'; "use strict";
import { Uint8Array } from "../utils/buffs";
import { Z_UNKNOWN } from "./constants";
// (C) 1995-2013 Jean-loup Gailly and Mark Adler // (C) 1995-2013 Jean-loup Gailly and Mark Adler
// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin
@ -19,29 +22,27 @@
// misrepresented as being the original software. // misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution. // 3. This notice may not be removed or altered from any source distribution.
function ZStream() { export class ZStream<State> {
/* next input byte */ /* next input byte */
this.input = null; // JS specific, because we have no pointers public input!: Uint8Array; // JS specific, because we have no pointers
this.next_in = 0; public next_in = 0;
/* number of bytes available at input */ /* number of bytes available at input */
this.avail_in = 0; public avail_in = 0;
/* total number of input bytes read so far */ /* total number of input bytes read so far */
this.total_in = 0; public total_in = 0;
/* next output byte should be put there */ /* next output byte should be put there */
this.output = null; // JS specific, because we have no pointers public output!: Uint8Array; // JS specific, because we have no pointers
this.next_out = 0; public next_out = 0;
/* remaining free space at output */ /* remaining free space at output */
this.avail_out = 0; public avail_out = 0;
/* total number of bytes output so far */ /* total number of bytes output so far */
this.total_out = 0; public total_out = 0;
/* last error message, NULL if no error */ /* last error message, NULL if no error */
this.msg = ''/*Z_NULL*/; public msg?: string /*Z_NULL*/;
/* not visible by applications */ /* not visible by applications */
this.state = null; public state!: State;
/* best guess about the data type: binary or text */ /* best guess about the data type: binary or text */
this.data_type = 2/*Z_UNKNOWN*/; public data_type = Z_UNKNOWN;
/* adler32 value of the uncompressed data */ /* adler32 value of the uncompressed data */
this.adler = 0; public adler = 0;
} }
module.exports = ZStream;