UNPKG

@gmod/cram

Version:

read CRAM files with pure Javascript

197 lines 7.61 kB
// @ts-nocheck import { CramMalformedError } from "../errors.js"; import D04 from "./d04.js"; import D14 from "./d14.js"; import Decoding from "./decoding.js"; import { readStatsO0, readStatsO1 } from "./frequencies.js"; // const /* int */ ORDER_BYTE_LENGTH = 1 // const /* int */ COMPRESSED_BYTE_LENGTH = 4 const /* int */ RAW_BYTE_LENGTH = 4; // const /* int */ PREFIX_BYTE_LENGTH = // ORDER_BYTE_LENGTH + COMPRESSED_BYTE_LENGTH + RAW_BYTE_LENGTH // enum ORDER { // ZERO, ONE; // static ORDER fromInt(const /* int */ value) { // try { // return ORDER.values()[value]; // } catch (const ArrayIndexOutOfBoundsException e) { // throw new RuntimeException("Unknown rANS order: " + value); // } // } // } // static ByteBuffer compress(const ByteBuffer input, const ORDER order, const ByteBuffer out) { // if (input.remaining() == 0) // return EMPTY_BUFFER; // if (input.remaining() < 4) // return encode_order0_way4(input, out); // switch (order) { // case ZERO: // return encode_order0_way4(input, out); // case ONE: // return encode_order1_way4(input, out); // default: // throw new RuntimeException("Unknown rANS order: " + order); // } // } // static /* ByteBuffer */ allocateIfNeeded(/* const int */ in_size, // /* const ByteBuffer */ out_buf) { // const /* int */ compressedSize = (/* int */) (1.05 * in_size + 257 * 257 * 3 + 4); // if (out_buf == null) // return ByteBuffer.allocate(compressedSize); // if (out_buf.remaining() < compressedSize) // throw new RuntimeException("Insufficient buffer size."); // out_buf.order(ByteOrder.LITTLE_ENDIAN); // return out_buf; // } // static ByteBuffer encode_order0_way4(const ByteBuffer input, // ByteBuffer out_buf) { // const /* int */ in_size = input.remaining(); // out_buf = allocateIfNeeded(in_size, out_buf); // const /* int */ freqTableStart = PREFIX_BYTE_LENGTH; // out_buf.position(freqTableStart); // const /* int */[] F = Frequencies.calcFrequencies_o0(in); // const RansEncSymbol[] syms = Frequencies.buildSyms_o0(F); // const ByteBuffer cp = out_buf.slice(); // const /* int */ frequencyTable_size = Frequencies.writeFrequencies_o0(cp, F); // input.rewind(); // const /* int */ compressedBlob_size = E04.compress(input, syms, cp); // finalizeCompressed(0, out_buf, in_size, frequencyTable_size, // compressedBlob_size); // return out_buf; // } // static ByteBuffer encode_order1_way4(const ByteBuffer input, // ByteBuffer out_buf) { // const /* int */ in_size = input.remaining(); // out_buf = allocateIfNeeded(in_size, out_buf); // const /* int */ freqTableStart = PREFIX_BYTE_LENGTH; // out_buf.position(freqTableStart); // const /* int */[][] F = Frequencies.calcFrequencies_o1(in); // const RansEncSymbol[][] syms = Frequencies.buildSyms_o1(F); // const ByteBuffer cp = out_buf.slice(); // const /* int */ frequencyTable_size = Frequencies.writeFrequencies_o1(cp, F); // input.rewind(); // const /* int */ compressedBlob_size = E14.compress(input, syms, cp); // finalizeCompressed(1, out_buf, in_size, frequencyTable_size, // compressedBlob_size); // return out_buf; // } // static void finalizeCompressed(const /* int */ order, const ByteBuffer out_buf, // const /* int */ in_size, const /* int */ frequencyTable_size, const /* int */ compressedBlob_size) { // out_buf.limit(PREFIX_BYTE_LENGTH + frequencyTable_size // + compressedBlob_size); // out_buf.put(0, (byte) order); // out_buf.order(ByteOrder.LITTLE_ENDIAN); // const /* int */ compressedSizeOffset = ORDER_BYTE_LENGTH; // out_buf.putInt(compressedSizeOffset, frequencyTable_size // + compressedBlob_size); // const /* int */ rawSizeOffset = ORDER_BYTE_LENGTH + COMPRESSED_BYTE_LENGTH; // out_buf.putInt(rawSizeOffset, in_size); // out_buf.rewind(); // } function uncompressOrder0Way4( /* const ByteBuffer */ input, /* const ByteBuffer */ out) { // input.order(ByteOrder.LITTLE_ENDIAN); const D = new Decoding.AriDecoder(); const syms = new Array(256); for (let i = 0; i < syms.length; i += 1) { syms[i] = new Decoding.DecodingSymbol(); } readStatsO0(input, D, syms); D04(input, D, syms, out); return out; } function uncompressOrder1Way4( /* const ByteBuffer */ input, /* const ByteBuffer */ output) { const D = new Array(256); for (let i = 0; i < D.length; i += 1) { D[i] = new Decoding.AriDecoder(); } const /* Decoding.RansDecSymbol[][] */ syms = new Array(256); for (let i = 0; i < syms.length; i += 1) { syms[i] = new Array(256); for (let j = 0; j < syms[i].length; j += 1) { syms[i][j] = new Decoding.DecodingSymbol(); } } readStatsO1(input, D, syms); D14(input, output, D, syms); return output; } /* compat layer to make a node buffer act like a java ByteBuffer */ class ByteBuffer { constructor(nodeBuffer, initialInputPosition = 0) { this._buffer = nodeBuffer; this._dataView = new DataView(nodeBuffer.buffer); this._position = initialInputPosition; this.length = nodeBuffer.length; } get() { const b = this._buffer[this._position]; this._position += 1; return b; } getByte() { return this.get(); } getByteAt(position) { return this._buffer[position]; } position() { return this._position; } put(val) { this._buffer[this._position] = val; this._position += 1; return val; } putAt(position, val) { this._buffer[position] = val; return val; } setPosition(pos) { this._position = pos; return pos; } getInt() { const i = this._dataView.getInt32(this._position, true); this._position += 4; return i; } remaining() { return this._buffer.length - this._position; } } // static /* const */ ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); export default function uncompress(inputBuffer, outputBuffer, initialInputPosition = 0) { if (inputBuffer.length === 0) { outputBuffer.fill(0); return outputBuffer; } const input = new ByteBuffer(inputBuffer, initialInputPosition); // input.order(ByteOrder.LITTLE_ENDIAN); const order = input.get(); if (order !== 0 && order !== 1) { throw new CramMalformedError(`Invalid rANS order ${order}`); } const /* int */ inputSize = input.getInt(); if (inputSize !== input.remaining() - RAW_BYTE_LENGTH) { throw new CramMalformedError('Incorrect input length.'); } const /* int */ outputSize = input.getInt(); const output = new ByteBuffer(outputBuffer || new Uint8Array(outputSize)); // TODO output.limit(outputSize) if (output.length < outputSize) { throw new CramMalformedError(`Output buffer too small to fit ${outputSize} bytes.`); } switch (order) { case 0: return uncompressOrder0Way4(input, output); case 1: return uncompressOrder1Way4(input, output); default: throw new CramMalformedError(`Invalid rANS order: ${order}`); } } //# sourceMappingURL=index.js.map