@fdm-monster/server
Version:
FDM Monster is a bulk OctoPrint, Klipper, PrusaLink and BambuLab manager to set up, configure and monitor 3D printers. Our aim is to provide neat overview over your farm.
132 lines (131 loc) • 3.56 kB
JavaScript
//#region src/utils/bgcode/heatshrink-decoder.ts
var HeatshrinkDecoder = class {
windowBits;
lookaheadBits;
windowSize;
window;
head = 0;
state = 0;
outputIndex = 0;
outputCount = 0;
inputBuffer;
inputIndex = 0;
bitAccumulator = 0;
bitsAvailable = 0;
constructor(windowBits, lookaheadBits) {
this.windowBits = windowBits;
this.lookaheadBits = lookaheadBits;
this.windowSize = 1 << windowBits;
this.window = Buffer.alloc(this.windowSize);
this.inputBuffer = Buffer.alloc(0);
}
decompress(input) {
this.inputBuffer = input;
this.inputIndex = 0;
this.bitAccumulator = 0;
this.bitsAvailable = 0;
this.head = 0;
this.state = 0;
const output = [];
while (this.inputIndex < this.inputBuffer.length || this.bitsAvailable > 0) {
const result = this.step();
if (result === null) break;
if (result >= 0) output.push(result);
}
return Buffer.from(output);
}
step() {
switch (this.state) {
case 0: return this.handleTagBit();
case 1: return this.handleYieldLiteral();
case 2: return this.handleBackrefIndexMSB();
case 3: return this.handleBackrefIndexLSB();
case 4: return this.handleBackrefCountMSB();
case 5: return this.handleBackrefCountLSB();
case 6: return this.handleYieldBackref();
default: return null;
}
}
readBits(count) {
while (this.bitsAvailable < count && this.inputIndex < this.inputBuffer.length) {
this.bitAccumulator = this.bitAccumulator << 8 | this.inputBuffer[this.inputIndex++];
this.bitsAvailable += 8;
}
if (this.bitsAvailable < count) return null;
this.bitsAvailable -= count;
const result = this.bitAccumulator >> this.bitsAvailable & (1 << count) - 1;
this.bitAccumulator &= (1 << this.bitsAvailable) - 1;
return result;
}
handleTagBit() {
const bit = this.readBits(1);
if (bit === null) return null;
if (bit === 1) this.state = 1;
else if (this.windowBits > 8) this.state = 2;
else {
this.outputIndex = 0;
this.state = 3;
}
return -1;
}
handleYieldLiteral() {
const byte = this.readBits(8);
if (byte === null) return null;
this.pushByte(byte);
this.state = 0;
return byte;
}
handleBackrefIndexMSB() {
const msb = this.readBits(this.windowBits - 8);
if (msb === null) return null;
this.outputIndex = msb << 8;
this.state = 3;
return -1;
}
handleBackrefIndexLSB() {
const bits = this.windowBits > 8 ? 8 : this.windowBits;
const lsb = this.readBits(bits);
if (lsb === null) return null;
this.outputIndex |= lsb;
this.outputCount = 0;
if (this.lookaheadBits > 8) this.state = 4;
else this.state = 5;
return -1;
}
handleBackrefCountMSB() {
const msb = this.readBits(this.lookaheadBits - 8);
if (msb === null) return null;
this.outputCount = msb << 8;
this.state = 5;
return -1;
}
handleBackrefCountLSB() {
const bits = this.lookaheadBits > 8 ? 8 : this.lookaheadBits;
const lsb = this.readBits(bits);
if (lsb === null) return null;
this.outputCount |= lsb;
this.outputCount += 1;
this.outputIndex += 1;
this.state = 6;
return -1;
}
handleYieldBackref() {
if (this.outputCount === 0) {
this.state = 0;
return -1;
}
const pos = (this.head - this.outputIndex + this.windowSize) % this.windowSize;
const byte = this.window[pos];
this.pushByte(byte);
this.outputCount--;
if (this.outputCount === 0) this.state = 0;
return byte;
}
pushByte(byte) {
this.window[this.head] = byte;
this.head = (this.head + 1) % this.windowSize;
}
};
//#endregion
export { HeatshrinkDecoder };
//# sourceMappingURL=heatshrink-decoder.js.map