@gmod/cram
Version:
read CRAM files with pure Javascript
52 lines • 1.8 kB
JavaScript
import CramCodec from "./_base.js";
import { CramUnimplementedError } from "../../errors.js";
export default class SubexpCodec extends CramCodec {
constructor(parameters, dataType) {
super(parameters, dataType);
if (this.dataType !== 'int') {
throw new CramUnimplementedError(`${this.dataType} decoding not yet implemented by SUBEXP codec`);
}
}
decode(_slice, coreDataBlock, _blocksByContentId, cursors) {
return decodeSubexpInline(coreDataBlock.content, cursors.coreBlock, this.parameters.K, this.parameters.offset);
}
}
/**
* Optimized subexp decoder with inlined bit reading.
*/
function decodeSubexpInline(data, cursor, K, offset) {
let { bytePosition, bitPosition } = cursor;
// Count leading ones (inline single-bit reads)
let numLeadingOnes = 0;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
const bit = (data[bytePosition] >> bitPosition) & 1;
bitPosition -= 1;
if (bitPosition < 0) {
bytePosition += 1;
bitPosition = 7;
}
if (bit === 0) {
break;
}
numLeadingOnes += 1;
}
// Determine how many bits to read for the value
const b = numLeadingOnes === 0 ? K : numLeadingOnes + K - 1;
// Read b bits
let bits = 0;
for (let i = 0; i < b; i++) {
bits <<= 1;
bits |= (data[bytePosition] >> bitPosition) & 1;
bitPosition -= 1;
if (bitPosition < 0) {
bytePosition += 1;
bitPosition = 7;
}
}
cursor.bytePosition = bytePosition;
cursor.bitPosition = bitPosition;
const n = numLeadingOnes === 0 ? bits : (1 << b) | bits;
return n - offset;
}
//# sourceMappingURL=subexp.js.map