@gmod/bgzf-filehandle
Version:
read from a compressed bgzip file (with .gzi) as if it were uncompressed
37 lines • 1.79 kB
JavaScript
import GziIndex from "./gziIndex.js";
import { unzip } from "./unzip.js";
import { concatUint8Array } from "./util.js";
export default class BgzFilehandle {
constructor({ filehandle, gziFilehandle, }) {
this.filehandle = filehandle;
this.gzi = new GziIndex({
filehandle: gziFilehandle,
});
}
async _readAndUncompressBlock(compressedPosition, nextCompressedPosition) {
let next = nextCompressedPosition;
if (!next) {
next = (await this.filehandle.stat()).size;
}
// read the compressed data into the block buffer
const blockCompressedLength = next - compressedPosition;
const blockBuffer = await this.filehandle.read(blockCompressedLength, compressedPosition);
// uncompress it
return unzip(blockBuffer);
}
async read(length, position) {
const blockPositions = await this.gzi.getRelevantBlocksForRead(length, position);
const blocks = [];
for (let blockNum = 0; blockNum < blockPositions.length - 1; blockNum += 1) {
const uncompressedBuffer = await this._readAndUncompressBlock(blockPositions[blockNum][0], blockPositions[blockNum + 1][0]);
const [, uncompressedPosition] = blockPositions[blockNum];
const sourceOffset = uncompressedPosition >= position ? 0 : position - uncompressedPosition;
const sourceEnd = Math.min(position + length, uncompressedPosition + uncompressedBuffer.length) - uncompressedPosition;
if (sourceOffset >= 0 && sourceOffset < uncompressedBuffer.length) {
blocks.push(uncompressedBuffer.subarray(sourceOffset, sourceEnd));
}
}
return concatUint8Array(blocks);
}
}
//# sourceMappingURL=bgzFilehandle.js.map