221 lines
4.7 KiB
JavaScript
221 lines
4.7 KiB
JavaScript
'use strict';
|
|
|
|
exports.compress = compress;
|
|
exports.decompress = decompress;
|
|
exports.compressSync = compressSync;
|
|
exports.decompressSync = decompressSync;
|
|
exports.compressStream = compressStream;
|
|
exports.decompressStream = decompressStream;
|
|
|
|
const iltorb = require('./build/bindings/iltorb.node');
|
|
const Transform = require('stream').Transform;
|
|
|
|
class TransformStreamEncode extends Transform {
|
|
constructor(params, sync) {
|
|
super();
|
|
this.sync = sync || false;
|
|
this.encoding = false;
|
|
this.corked = false;
|
|
this.flushing = false;
|
|
this.encoder = new iltorb.StreamEncode(params || {});
|
|
}
|
|
|
|
_transform(chunk, encoding, next) {
|
|
this.encoding = true;
|
|
this.encoder.transform(chunk, (err, output) => {
|
|
this.encoding = false;
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
this._push(output);
|
|
next();
|
|
if (this.flushing) {
|
|
this.flush(true);
|
|
}
|
|
}, !this.sync);
|
|
}
|
|
|
|
_flush(done) {
|
|
this.encoder.flush(true, (err, output) => {
|
|
if (err) {
|
|
return done(err);
|
|
}
|
|
this._push(output);
|
|
done();
|
|
}, !this.sync);
|
|
}
|
|
|
|
_push(output) {
|
|
if (output) {
|
|
for (let i = 0; i < output.length; i++) {
|
|
this.push(output[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
flush(force) {
|
|
if (this.flushing && !force) {
|
|
return;
|
|
}
|
|
|
|
if (!this.corked) {
|
|
this.cork();
|
|
}
|
|
this.corked = true;
|
|
this.flushing = true;
|
|
|
|
if (this.encoding) {
|
|
return;
|
|
}
|
|
|
|
this.encoder.flush(false, (err, output) => {
|
|
if (err) {
|
|
this.emit('error', err);
|
|
} else {
|
|
this._push(output);
|
|
}
|
|
this.corked = false;
|
|
this.flushing = false;
|
|
this.uncork();
|
|
}, true);
|
|
}
|
|
}
|
|
|
|
class TransformStreamDecode extends Transform {
|
|
constructor(sync) {
|
|
super();
|
|
this.sync = sync || false;
|
|
this.decoder = new iltorb.StreamDecode();
|
|
}
|
|
|
|
_transform(chunk, encoding, next) {
|
|
this.decoder.transform(chunk, (err, output) => {
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
this._push(output);
|
|
next();
|
|
}, !this.sync);
|
|
}
|
|
|
|
_flush(done) {
|
|
this.decoder.flush((err, output) => {
|
|
if (err) {
|
|
return done(err);
|
|
}
|
|
this._push(output);
|
|
done();
|
|
}, !this.sync);
|
|
}
|
|
|
|
_push(output) {
|
|
if (output) {
|
|
for (let i = 0; i < output.length; i++) {
|
|
this.push(output[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function compress(input, params, cb) {
|
|
if (arguments.length === 2) {
|
|
cb = params;
|
|
params = {};
|
|
}
|
|
if (!Buffer.isBuffer(input)) {
|
|
process.nextTick(cb, new Error('Brotli input is not a buffer.'));
|
|
return;
|
|
}
|
|
if (typeof cb !== 'function') {
|
|
process.nextTick(cb, new Error('Second argument is not a function.'));
|
|
return;
|
|
}
|
|
if (typeof params !== 'object') {
|
|
params = {};
|
|
}
|
|
params.size_hint = input.length;
|
|
const stream = new TransformStreamEncode(params);
|
|
const chunks = [];
|
|
let length = 0;
|
|
stream.on('error', cb);
|
|
stream.on('data', function(c) {
|
|
chunks.push(c);
|
|
length += c.length;
|
|
});
|
|
stream.on('end', function() {
|
|
cb(null, Buffer.concat(chunks, length));
|
|
});
|
|
stream.end(input);
|
|
}
|
|
|
|
function decompress(input, cb) {
|
|
if (!Buffer.isBuffer(input)) {
|
|
process.nextTick(cb, new Error('Brotli input is not a buffer.'));
|
|
return;
|
|
}
|
|
if (typeof cb !== 'function') {
|
|
process.nextTick(cb, new Error('Second argument is not a function.'));
|
|
return;
|
|
}
|
|
const stream = new TransformStreamDecode();
|
|
const chunks = [];
|
|
let length = 0;
|
|
stream.on('error', cb);
|
|
stream.on('data', function(c) {
|
|
chunks.push(c);
|
|
length += c.length;
|
|
});
|
|
stream.on('end', function() {
|
|
cb(null, Buffer.concat(chunks, length));
|
|
});
|
|
stream.end(input);
|
|
}
|
|
|
|
function compressSync(input, params) {
|
|
if (!Buffer.isBuffer(input)) {
|
|
throw new Error('Brotli input is not a buffer.');
|
|
}
|
|
if (typeof params !== 'object') {
|
|
params = {};
|
|
}
|
|
params.size_hint = input.length;
|
|
const stream = new TransformStreamEncode(params, true);
|
|
const chunks = [];
|
|
let length = 0;
|
|
stream.on('error', function(e) {
|
|
throw e;
|
|
});
|
|
stream.on('data', function(c) {
|
|
chunks.push(c);
|
|
length += c.length;
|
|
});
|
|
stream.end(input);
|
|
return Buffer.concat(chunks, length);
|
|
}
|
|
|
|
function decompressSync(input) {
|
|
if (!Buffer.isBuffer(input)) {
|
|
throw new Error('Brotli input is not a buffer.');
|
|
}
|
|
const stream = new TransformStreamDecode(true);
|
|
const chunks = [];
|
|
let length = 0;
|
|
stream.on('error', function(e) {
|
|
throw e;
|
|
});
|
|
stream.on('data', function(c) {
|
|
chunks.push(c);
|
|
length += c.length;
|
|
});
|
|
stream.end(input);
|
|
return Buffer.concat(chunks, length);
|
|
}
|
|
|
|
function compressStream(params) {
|
|
return new TransformStreamEncode(params);
|
|
}
|
|
|
|
function decompressStream() {
|
|
return new TransformStreamDecode();
|
|
}
|