react-zlib-js
Version:
Pure javascript implementation of Zlib nodejs core module. The zlib module provides compression functionality implemented using Gzip, Deflate/Inflate, and Brotli. Compatible with Node.js 22.x LTS.
982 lines (788 loc) • 27.6 kB
JavaScript
'use strict';
var Buffer = require('buffer').Buffer;
var Transform = require('stream').Transform;
var binding = require('./binding');
var brotliBinding = require('./brotli-binding');
var util = require('util');
var assert = require('assert').ok;
var kMaxLength = require('buffer').kMaxLength;
var kRangeErrorMessage = 'Cannot create final Buffer. It would be larger than 0x' + kMaxLength.toString(16) + ' bytes';
// zlib doesn't provide these, so kludge them in following the same
// const naming scheme zlib uses.
binding.Z_MIN_WINDOWBITS = 8;
binding.Z_MAX_WINDOWBITS = 15;
binding.Z_DEFAULT_WINDOWBITS = 15;
binding.Z_MIN_CHUNK = 64;
binding.Z_MAX_CHUNK = Infinity;
binding.Z_DEFAULT_CHUNK = 16 * 1024;
binding.Z_MIN_MEMLEVEL = 1;
binding.Z_MAX_MEMLEVEL = 9;
binding.Z_DEFAULT_MEMLEVEL = 8;
binding.Z_MIN_LEVEL = -1;
binding.Z_MAX_LEVEL = 9;
binding.Z_DEFAULT_LEVEL = binding.Z_DEFAULT_COMPRESSION;
// expose all the zlib constants
var bkeys = Object.keys(binding);
for (var bk = 0; bk < bkeys.length; bk++) {
var bkey = bkeys[bk];
if ((bkey.match(/^Z/) || bkey.match(/^BROTLI/)) && bkey !== 'Zlib') {
Object.defineProperty(exports, bkey, {
enumerable: true, value: binding[bkey], writable: false
});
}
}
// Create a constants object (Node.js 7.0.0+)
var constants = {};
for (var ck = 0; ck < bkeys.length; ck++) {
var ckey = bkeys[ck];
if ((ckey.match(/^Z/) || ckey.match(/^BROTLI/)) && ckey !== 'Zlib') {
constants[ckey] = binding[ckey];
}
}
Object.defineProperty(exports, 'constants', {
enumerable: true, value: Object.freeze(constants), writable: false
});
// translation table for return codes.
var codes = {
Z_OK: binding.Z_OK,
Z_STREAM_END: binding.Z_STREAM_END,
Z_NEED_DICT: binding.Z_NEED_DICT,
Z_ERRNO: binding.Z_ERRNO,
Z_STREAM_ERROR: binding.Z_STREAM_ERROR,
Z_DATA_ERROR: binding.Z_DATA_ERROR,
Z_MEM_ERROR: binding.Z_MEM_ERROR,
Z_BUF_ERROR: binding.Z_BUF_ERROR,
Z_VERSION_ERROR: binding.Z_VERSION_ERROR
};
var codeKeys = Object.keys(codes);
for (var i = 0; i < codeKeys.length; i++) {
var codeKey = codeKeys[i];
codes[codes[codeKey]] = codeKey;
}
Object.defineProperty(exports, 'codes', {
enumerable: true, value: Object.freeze(codes), writable: false
});
// Deflate/Inflate classes
exports.Deflate = Deflate;
exports.Inflate = Inflate;
exports.Gzip = Gzip;
exports.Gunzip = Gunzip;
exports.DeflateRaw = DeflateRaw;
exports.InflateRaw = InflateRaw;
exports.Unzip = Unzip;
// Brotli classes (Node.js 11.7.0+)
exports.BrotliCompress = BrotliCompress;
exports.BrotliDecompress = BrotliDecompress;
// Factory functions
exports.createDeflate = function (o) {
return new Deflate(o);
};
exports.createInflate = function (o) {
return new Inflate(o);
};
exports.createDeflateRaw = function (o) {
return new DeflateRaw(o);
};
exports.createInflateRaw = function (o) {
return new InflateRaw(o);
};
exports.createGzip = function (o) {
return new Gzip(o);
};
exports.createGunzip = function (o) {
return new Gunzip(o);
};
exports.createUnzip = function (o) {
return new Unzip(o);
};
// Brotli factory functions (Node.js 11.7.0+)
exports.createBrotliCompress = function (o) {
return new BrotliCompress(o);
};
exports.createBrotliDecompress = function (o) {
return new BrotliDecompress(o);
};
// Convenience methods - deflate/inflate
exports.deflate = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new Deflate(opts), buffer, callback);
};
exports.deflateSync = function (buffer, opts) {
return zlibBufferSync(new Deflate(opts), buffer);
};
exports.gzip = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new Gzip(opts), buffer, callback);
};
exports.gzipSync = function (buffer, opts) {
return zlibBufferSync(new Gzip(opts), buffer);
};
exports.deflateRaw = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new DeflateRaw(opts), buffer, callback);
};
exports.deflateRawSync = function (buffer, opts) {
return zlibBufferSync(new DeflateRaw(opts), buffer);
};
exports.unzip = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new Unzip(opts), buffer, callback);
};
exports.unzipSync = function (buffer, opts) {
return zlibBufferSync(new Unzip(opts), buffer);
};
exports.inflate = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new Inflate(opts), buffer, callback);
};
exports.inflateSync = function (buffer, opts) {
return zlibBufferSync(new Inflate(opts), buffer);
};
exports.gunzip = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new Gunzip(opts), buffer, callback);
};
exports.gunzipSync = function (buffer, opts) {
return zlibBufferSync(new Gunzip(opts), buffer);
};
exports.inflateRaw = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return zlibBuffer(new InflateRaw(opts), buffer, callback);
};
exports.inflateRawSync = function (buffer, opts) {
return zlibBufferSync(new InflateRaw(opts), buffer);
};
// Brotli convenience methods (Node.js 11.7.0+)
exports.brotliCompress = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return brotliBuffer(new BrotliCompress(opts), buffer, callback);
};
exports.brotliCompressSync = function (buffer, opts) {
return brotliBufferSync(new BrotliCompress(opts), buffer);
};
exports.brotliDecompress = function (buffer, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return brotliBuffer(new BrotliDecompress(opts), buffer, callback);
};
exports.brotliDecompressSync = function (buffer, opts) {
return brotliBufferSync(new BrotliDecompress(opts), buffer);
};
// Helper functions
function zlibBuffer(engine, buffer, callback) {
var buffers = [];
var nread = 0;
engine.on('error', onError);
engine.on('end', onEnd);
engine.end(buffer);
flow();
function flow() {
var chunk;
while (null !== (chunk = engine.read())) {
buffers.push(chunk);
nread += chunk.length;
}
engine.once('readable', flow);
}
function onError(err) {
engine.removeListener('end', onEnd);
engine.removeListener('readable', flow);
callback(err);
}
function onEnd() {
var buf;
var err = null;
if (nread >= kMaxLength) {
err = new RangeError(kRangeErrorMessage);
} else {
buf = Buffer.concat(buffers, nread);
}
buffers = [];
engine.close();
callback(err, buf);
}
}
function zlibBufferSync(engine, buffer) {
if (typeof buffer === 'string') buffer = Buffer.from(buffer);
// Handle Uint8Array and other typed arrays
if (!Buffer.isBuffer(buffer)) {
if (buffer instanceof Uint8Array || ArrayBuffer.isView(buffer)) {
buffer = Buffer.from(buffer);
} else {
throw new TypeError('Not a string or buffer');
}
}
var flushFlag = engine._finishFlushFlag;
return engine._processChunk(buffer, flushFlag);
}
function brotliBuffer(engine, buffer, callback) {
var buffers = [];
var nread = 0;
engine.on('error', onError);
engine.on('end', onEnd);
engine.end(buffer);
flow();
function flow() {
var chunk;
while (null !== (chunk = engine.read())) {
buffers.push(chunk);
nread += chunk.length;
}
engine.once('readable', flow);
}
function onError(err) {
engine.removeListener('end', onEnd);
engine.removeListener('readable', flow);
callback(err);
}
function onEnd() {
var buf;
var err = null;
if (nread >= kMaxLength) {
err = new RangeError(kRangeErrorMessage);
} else {
buf = Buffer.concat(buffers, nread);
}
buffers = [];
engine.close();
callback(err, buf);
}
}
function brotliBufferSync(engine, buffer) {
if (typeof buffer === 'string') buffer = Buffer.from(buffer);
// Handle Uint8Array and other typed arrays
if (!Buffer.isBuffer(buffer)) {
if (buffer instanceof Uint8Array || ArrayBuffer.isView(buffer)) {
buffer = Buffer.from(buffer);
} else {
throw new TypeError('Not a string or buffer');
}
}
var flushFlag = engine._finishFlushFlag;
return engine._processChunk(buffer, flushFlag);
}
// Deflate class
function Deflate(opts) {
if (!(this instanceof Deflate)) return new Deflate(opts);
Zlib.call(this, opts, binding.DEFLATE);
}
function Inflate(opts) {
if (!(this instanceof Inflate)) return new Inflate(opts);
Zlib.call(this, opts, binding.INFLATE);
}
function Gzip(opts) {
if (!(this instanceof Gzip)) return new Gzip(opts);
Zlib.call(this, opts, binding.GZIP);
}
function Gunzip(opts) {
if (!(this instanceof Gunzip)) return new Gunzip(opts);
Zlib.call(this, opts, binding.GUNZIP);
}
function DeflateRaw(opts) {
if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts);
Zlib.call(this, opts, binding.DEFLATERAW);
}
function InflateRaw(opts) {
if (!(this instanceof InflateRaw)) return new InflateRaw(opts);
Zlib.call(this, opts, binding.INFLATERAW);
}
function Unzip(opts) {
if (!(this instanceof Unzip)) return new Unzip(opts);
Zlib.call(this, opts, binding.UNZIP);
}
function isValidFlushFlag(flag) {
return flag === binding.Z_NO_FLUSH || flag === binding.Z_PARTIAL_FLUSH || flag === binding.Z_SYNC_FLUSH || flag === binding.Z_FULL_FLUSH || flag === binding.Z_FINISH || flag === binding.Z_BLOCK;
}
// Zlib base class
function Zlib(opts, mode) {
var _this = this;
this._opts = opts = opts || {};
this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK;
Transform.call(this, opts);
if (opts.flush && !isValidFlushFlag(opts.flush)) {
throw new Error('Invalid flush flag: ' + opts.flush);
}
if (opts.finishFlush && !isValidFlushFlag(opts.finishFlush)) {
throw new Error('Invalid flush flag: ' + opts.finishFlush);
}
this._flushFlag = opts.flush || binding.Z_NO_FLUSH;
this._finishFlushFlag = typeof opts.finishFlush !== 'undefined' ? opts.finishFlush : binding.Z_FINISH;
if (opts.chunkSize) {
if (opts.chunkSize < exports.Z_MIN_CHUNK || opts.chunkSize > exports.Z_MAX_CHUNK) {
throw new Error('Invalid chunk size: ' + opts.chunkSize);
}
}
if (opts.windowBits) {
if (opts.windowBits < exports.Z_MIN_WINDOWBITS || opts.windowBits > exports.Z_MAX_WINDOWBITS) {
throw new Error('Invalid windowBits: ' + opts.windowBits);
}
}
if (opts.level) {
if (opts.level < exports.Z_MIN_LEVEL || opts.level > exports.Z_MAX_LEVEL) {
throw new Error('Invalid compression level: ' + opts.level);
}
}
if (opts.memLevel) {
if (opts.memLevel < exports.Z_MIN_MEMLEVEL || opts.memLevel > exports.Z_MAX_MEMLEVEL) {
throw new Error('Invalid memLevel: ' + opts.memLevel);
}
}
if (opts.strategy) {
if (opts.strategy != exports.Z_FILTERED && opts.strategy != exports.Z_HUFFMAN_ONLY && opts.strategy != exports.Z_RLE && opts.strategy != exports.Z_FIXED && opts.strategy != exports.Z_DEFAULT_STRATEGY) {
throw new Error('Invalid strategy: ' + opts.strategy);
}
}
if (opts.dictionary) {
if (!Buffer.isBuffer(opts.dictionary)) {
throw new Error('Invalid dictionary: it should be a Buffer instance');
}
}
this._handle = new binding.Zlib(mode);
var self = this;
this._hadError = false;
this._handle.onerror = function (message, errno) {
_close(self);
self._hadError = true;
var error = new Error(message);
error.errno = errno;
error.code = exports.codes[errno];
self.emit('error', error);
};
var level = exports.Z_DEFAULT_COMPRESSION;
if (typeof opts.level === 'number') level = opts.level;
var strategy = exports.Z_DEFAULT_STRATEGY;
if (typeof opts.strategy === 'number') strategy = opts.strategy;
this._handle.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS, level, opts.memLevel || exports.Z_DEFAULT_MEMLEVEL, strategy, opts.dictionary);
this._buffer = Buffer.allocUnsafe(this._chunkSize);
this._offset = 0;
this._level = level;
this._strategy = strategy;
this.once('end', this.close);
Object.defineProperty(this, '_closed', {
get: function () {
return !_this._handle;
},
configurable: true,
enumerable: true
});
}
util.inherits(Zlib, Transform);
Zlib.prototype.params = function (level, strategy, callback) {
if (level < exports.Z_MIN_LEVEL || level > exports.Z_MAX_LEVEL) {
throw new RangeError('Invalid compression level: ' + level);
}
if (strategy != exports.Z_FILTERED && strategy != exports.Z_HUFFMAN_ONLY && strategy != exports.Z_RLE && strategy != exports.Z_FIXED && strategy != exports.Z_DEFAULT_STRATEGY) {
throw new TypeError('Invalid strategy: ' + strategy);
}
if (this._level !== level || this._strategy !== strategy) {
var self = this;
this.flush(binding.Z_SYNC_FLUSH, function () {
assert(self._handle, 'zlib binding closed');
self._handle.params(level, strategy);
if (!self._hadError) {
self._level = level;
self._strategy = strategy;
if (callback) callback();
}
});
} else {
process.nextTick(callback);
}
};
Zlib.prototype.reset = function () {
assert(this._handle, 'zlib binding closed');
return this._handle.reset();
};
Zlib.prototype._flush = function (callback) {
this._transform(Buffer.alloc(0), '', callback);
};
Zlib.prototype.flush = function (kind, callback) {
var _this2 = this;
var ws = this._writableState;
if (typeof kind === 'function' || kind === undefined && !callback) {
callback = kind;
kind = binding.Z_FULL_FLUSH;
}
if (ws.ended) {
if (callback) process.nextTick(callback);
} else if (ws.ending) {
if (callback) this.once('end', callback);
} else if (ws.needDrain) {
if (callback) {
this.once('drain', function () {
return _this2.flush(kind, callback);
});
}
} else {
this._flushFlag = kind;
this.write(Buffer.alloc(0), '', callback);
}
};
Zlib.prototype.close = function (callback) {
_close(this, callback);
process.nextTick(emitCloseNT, this);
};
function _close(engine, callback) {
if (callback) process.nextTick(callback);
if (!engine._handle) return;
engine._handle.close();
engine._handle = null;
}
function emitCloseNT(self) {
self.emit('close');
}
Zlib.prototype._transform = function (chunk, encoding, cb) {
var flushFlag;
var ws = this._writableState;
var ending = ws.ending || ws.ended;
var last = ending && (!chunk || ws.length === chunk.length);
if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input'));
if (!this._handle) return cb(new Error('zlib binding closed'));
if (last) flushFlag = this._finishFlushFlag;else {
flushFlag = this._flushFlag;
if (chunk.length >= ws.length) {
this._flushFlag = this._opts.flush || binding.Z_NO_FLUSH;
}
}
this._processChunk(chunk, flushFlag, cb);
};
Zlib.prototype._processChunk = function (chunk, flushFlag, cb) {
var availInBefore = chunk && chunk.length;
var availOutBefore = this._chunkSize - this._offset;
var inOff = 0;
var self = this;
var async = typeof cb === 'function';
if (!async) {
var buffers = [];
var nread = 0;
var error;
this.on('error', function (er) {
error = er;
});
assert(this._handle, 'zlib binding closed');
do {
var res = this._handle.writeSync(flushFlag, chunk, inOff, availInBefore, this._buffer, this._offset, availOutBefore);
} while (!this._hadError && callback(res[0], res[1]));
if (this._hadError) {
throw error;
}
if (nread >= kMaxLength) {
_close(this);
throw new RangeError(kRangeErrorMessage);
}
var buf = Buffer.concat(buffers, nread);
_close(this);
return buf;
}
assert(this._handle, 'zlib binding closed');
var req = this._handle.write(flushFlag, chunk, inOff, availInBefore, this._buffer, this._offset, availOutBefore);
req.buffer = chunk;
req.callback = callback;
function callback(availInAfter, availOutAfter) {
if (self._hadError) return false;
var have = availOutBefore - availOutAfter;
assert(have >= 0, 'have should not go down');
if (have > 0) {
var out = self._buffer.slice(self._offset, self._offset + have);
self._offset += have;
if (async) {
self.push(out);
} else {
buffers.push(out);
nread += out.length;
}
}
if (availOutAfter === 0 || self._offset >= self._chunkSize) {
availOutBefore = self._chunkSize;
self._offset = 0;
self._buffer = Buffer.allocUnsafe(self._chunkSize);
}
if (availOutAfter === 0) {
inOff += availInBefore - availInAfter;
availInBefore = availInAfter;
if (!async) return true;
var newReq = self._handle.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize);
newReq.callback = callback;
newReq.buffer = chunk;
return;
}
if (!async) return false;
cb();
}
};
util.inherits(Deflate, Zlib);
util.inherits(Inflate, Zlib);
util.inherits(Gzip, Zlib);
util.inherits(Gunzip, Zlib);
util.inherits(DeflateRaw, Zlib);
util.inherits(InflateRaw, Zlib);
util.inherits(Unzip, Zlib);
// Brotli classes (Node.js 11.7.0+)
function BrotliCompress(opts) {
if (!(this instanceof BrotliCompress)) return new BrotliCompress(opts);
BrotliBase.call(this, opts, binding.BROTLI_ENCODE);
}
function BrotliDecompress(opts) {
if (!(this instanceof BrotliDecompress)) return new BrotliDecompress(opts);
BrotliBase.call(this, opts, binding.BROTLI_DECODE);
}
function isValidBrotliFlushFlag(flag) {
return flag === binding.BROTLI_OPERATION_PROCESS ||
flag === binding.BROTLI_OPERATION_FLUSH ||
flag === binding.BROTLI_OPERATION_FINISH ||
flag === binding.BROTLI_OPERATION_EMIT_METADATA;
}
// BrotliBase class
function BrotliBase(opts, mode) {
var _this = this;
this._opts = opts = opts || {};
this._chunkSize = opts.chunkSize || exports.Z_DEFAULT_CHUNK;
Transform.call(this, opts);
if (opts.flush && !isValidBrotliFlushFlag(opts.flush)) {
throw new Error('Invalid flush flag: ' + opts.flush);
}
if (opts.finishFlush && !isValidBrotliFlushFlag(opts.finishFlush)) {
throw new Error('Invalid flush flag: ' + opts.finishFlush);
}
this._flushFlag = opts.flush || binding.BROTLI_OPERATION_PROCESS;
this._finishFlushFlag = typeof opts.finishFlush !== 'undefined' ? opts.finishFlush : binding.BROTLI_OPERATION_FINISH;
if (mode === binding.BROTLI_ENCODE) {
this._handle = new brotliBinding.BrotliEncoder(mode);
} else {
this._handle = new brotliBinding.BrotliDecoder(mode);
}
var self = this;
this._hadError = false;
this._handle.onerror = function (message, errno) {
_closeBrotli(self);
self._hadError = true;
var error = new Error(message);
error.errno = errno;
self.emit('error', error);
};
// Initialize with params
var params = opts.params || {};
this._handle.init(params);
this._buffer = Buffer.allocUnsafe(this._chunkSize);
this._offset = 0;
this.once('end', this.close);
Object.defineProperty(this, '_closed', {
get: function () {
return !_this._handle;
},
configurable: true,
enumerable: true
});
}
util.inherits(BrotliBase, Transform);
BrotliBase.prototype.reset = function () {
assert(this._handle, 'brotli binding closed');
// Brotli doesn't support reset, reinitialize
var params = this._opts.params || {};
this._handle.init(params);
};
BrotliBase.prototype._flush = function (callback) {
this._transform(Buffer.alloc(0), '', callback);
};
BrotliBase.prototype.flush = function (kind, callback) {
var _this2 = this;
var ws = this._writableState;
if (typeof kind === 'function' || kind === undefined && !callback) {
callback = kind;
kind = binding.BROTLI_OPERATION_FLUSH;
}
if (ws.ended) {
if (callback) process.nextTick(callback);
} else if (ws.ending) {
if (callback) this.once('end', callback);
} else if (ws.needDrain) {
if (callback) {
this.once('drain', function () {
return _this2.flush(kind, callback);
});
}
} else {
this._flushFlag = kind;
this.write(Buffer.alloc(0), '', callback);
}
};
BrotliBase.prototype.close = function (callback) {
_closeBrotli(this, callback);
process.nextTick(emitCloseNT, this);
};
function _closeBrotli(engine, callback) {
if (callback) process.nextTick(callback);
if (!engine._handle) return;
engine._handle.close();
engine._handle = null;
}
BrotliBase.prototype._transform = function (chunk, encoding, cb) {
var flushFlag;
var ws = this._writableState;
var ending = ws.ending || ws.ended;
var last = ending && (!chunk || ws.length === chunk.length);
if (chunk !== null && !Buffer.isBuffer(chunk)) return cb(new Error('invalid input'));
if (!this._handle) return cb(new Error('brotli binding closed'));
if (last) flushFlag = this._finishFlushFlag;else {
flushFlag = this._flushFlag;
if (chunk.length >= ws.length) {
this._flushFlag = this._opts.flush || binding.BROTLI_OPERATION_PROCESS;
}
}
this._processChunk(chunk, flushFlag, cb);
};
BrotliBase.prototype._processChunk = function (chunk, flushFlag, cb) {
var availInBefore = chunk && chunk.length;
var availOutBefore = this._chunkSize - this._offset;
var inOff = 0;
var self = this;
var async = typeof cb === 'function';
if (!async) {
var buffers = [];
var nread = 0;
var error;
this.on('error', function (er) {
error = er;
});
assert(this._handle, 'brotli binding closed');
do {
var res = this._handle.writeSync(flushFlag, chunk, inOff, availInBefore, this._buffer, this._offset, availOutBefore);
} while (!this._hadError && callback(res[0], res[1]));
if (this._hadError) {
throw error;
}
if (nread >= kMaxLength) {
_closeBrotli(this);
throw new RangeError(kRangeErrorMessage);
}
var buf = Buffer.concat(buffers, nread);
_closeBrotli(this);
return buf;
}
assert(this._handle, 'brotli binding closed');
var req = this._handle.write(flushFlag, chunk, inOff, availInBefore, this._buffer, this._offset, availOutBefore);
req.buffer = chunk;
req.callback = callback;
function callback(availInAfter, availOutAfter) {
if (self._hadError) return false;
var have = availOutBefore - availOutAfter;
assert(have >= 0, 'have should not go down');
if (have > 0) {
var out = self._buffer.slice(self._offset, self._offset + have);
self._offset += have;
if (async) {
self.push(out);
} else {
buffers.push(out);
nread += out.length;
}
}
if (availOutAfter === 0 || self._offset >= self._chunkSize) {
availOutBefore = self._chunkSize;
self._offset = 0;
self._buffer = Buffer.allocUnsafe(self._chunkSize);
}
if (availOutAfter === 0) {
inOff += availInBefore - availInAfter;
availInBefore = availInAfter;
if (!async) return true;
var newReq = self._handle.write(flushFlag, chunk, inOff, availInBefore, self._buffer, self._offset, self._chunkSize);
newReq.callback = callback;
newReq.buffer = chunk;
return;
}
if (!async) return false;
cb();
}
};
util.inherits(BrotliCompress, BrotliBase);
util.inherits(BrotliDecompress, BrotliBase);
// CRC32 function (Node.js 22.2.0+)
exports.crc32 = function(data, value) {
if (typeof data === 'string') {
data = Buffer.from(data);
}
if (!Buffer.isBuffer(data) && !(data instanceof Uint8Array)) {
throw new TypeError('data must be a string, Buffer, TypedArray, or DataView');
}
var crc = (value === undefined) ? 0 : value >>> 0;
crc = crc ^ 0xFFFFFFFF;
for (var i = 0; i < data.length; i++) {
crc = crc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >>> 8);
}
return (crc ^ 0xFFFFFFFF) >>> 0;
};
// CRC32 lookup table
var crc32Table = new Uint32Array([
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7d48, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd706bb,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
]);
exports.Zlib = Zlib;
exports.BrotliBase = BrotliBase;