smartarchive/ts/bzip2/index.ts

94 lines
2.5 KiB
TypeScript
Raw Permalink Normal View History

2023-11-11 17:28:50 +00:00
import * as plugins from '../plugins.js';
import { Bzip2 } from './bzip2.js';
import { bitIterator } from './bititerator.js';
export function unbzip2Stream() {
const bzip2Instance = new Bzip2();
var bufferQueue = [];
var hasBytes = 0;
var blockSize = 0;
var broken = false;
var done = false;
var bitReader = null;
var streamCRC = null;
function decompressBlock() {
if (!blockSize) {
blockSize = bzip2Instance.header(bitReader);
streamCRC = 0;
} else {
var bufsize = 100000 * blockSize;
var buf = new Int32Array(bufsize);
var chunk = [];
var f = function (b) {
chunk.push(b);
};
streamCRC = bzip2Instance.decompress(bitReader, f, buf, bufsize, streamCRC);
if (streamCRC === null) {
// reset for next bzip2 header
blockSize = 0;
return;
} else {
return Buffer.from(chunk);
}
}
}
var outlength = 0;
2023-11-13 19:00:28 +00:00
const decompressAndPush = async () => {
2023-11-11 17:28:50 +00:00
if (broken) return;
try {
const resultChunk = decompressBlock();
if (resultChunk) {
outlength += resultChunk.length;
}
2023-11-13 19:00:28 +00:00
return resultChunk;
2023-11-11 17:28:50 +00:00
} catch (e) {
console.error(e);
broken = true;
}
};
2023-11-13 21:11:24 +00:00
let counter = 0;
2023-11-11 17:28:50 +00:00
return new plugins.smartstream.SmartDuplex({
2023-11-13 21:11:24 +00:00
objectMode: true,
name: 'bzip2',
2023-11-14 09:58:01 +00:00
debug: false,
2023-11-13 21:11:24 +00:00
highWaterMark: 1,
2023-11-11 17:28:50 +00:00
writeFunction: async function (data, streamTools) {
2023-11-13 22:14:39 +00:00
// console.log(`got chunk ${counter++}`)
2023-11-11 17:28:50 +00:00
bufferQueue.push(data);
hasBytes += data.length;
if (bitReader === null) {
bitReader = bitIterator(function () {
return bufferQueue.shift();
});
}
while (!broken && hasBytes - bitReader.bytesRead + 1 >= (25000 + 100000 * blockSize || 4)) {
//console.error('decompressing with', hasBytes - bitReader.bytesRead + 1, 'bytes in buffer');
2023-11-13 19:00:28 +00:00
const result = await decompressAndPush();
2023-11-13 21:11:24 +00:00
if (!result) {
continue;
}
// console.log(result.toString());
2023-11-13 19:00:28 +00:00
await streamTools.push(result);
2023-11-11 17:28:50 +00:00
}
},
finalFunction: async function (streamTools) {
//console.error(x,'last compressing with', hasBytes, 'bytes in buffer');
while (!broken && bitReader && hasBytes > bitReader.bytesRead) {
2023-11-13 19:00:28 +00:00
const result = await decompressAndPush();
2023-11-14 12:17:05 +00:00
if (!result) {
continue;
}
2023-11-13 21:11:24 +00:00
await streamTools.push(result);
2023-11-11 17:28:50 +00:00
}
if (!broken) {
if (streamCRC !== null) this.emit('error', new Error('input stream ended prematurely'));
}
},
});
}