UNPKG

@gmod/cram

Version:

read CRAM files with pure Javascript

108 lines 4.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseItf8 = void 0; exports.batchDecodeItf8 = batchDecodeItf8; const _base_ts_1 = __importDefault(require("./_base.js")); const errors_ts_1 = require("../../errors.js"); const util_ts_1 = require("../util.js"); var util_ts_2 = require("../util.js"); Object.defineProperty(exports, "parseItf8", { enumerable: true, get: function () { return util_ts_2.parseItf8; } }); // Decode an entire buffer of ITF8 (variable-length int) values at once into // an Int32Array. ITF8 uses the high bits of the first byte to encode length: // 0xxxxxxx (1 byte, 7 bits), 10xxxxxx (2 bytes, 14 bits), 110xxxxx (3 bytes, // 21 bits), 1110xxxx (4 bytes, 28 bits), 1111xxxx (5 bytes, 32 bits). function batchDecodeItf8(buffer) { const result = new Int32Array(buffer.length); let count = 0; let pos = 0; const len = buffer.length; while (pos < len) { const b0 = buffer[pos]; if (b0 < 0x80) { result[count++] = b0; pos += 1; } else if (b0 < 0xc0) { result[count++] = ((b0 & 0x3f) << 8) | buffer[pos + 1]; pos += 2; } else if (b0 < 0xe0) { result[count++] = ((b0 & 0x1f) << 16) | (buffer[pos + 1] << 8) | buffer[pos + 2]; pos += 3; } else if (b0 < 0xf0) { result[count++] = ((b0 & 0x0f) << 24) | (buffer[pos + 1] << 16) | (buffer[pos + 2] << 8) | buffer[pos + 3]; pos += 4; } else { result[count++] = ((b0 & 0x0f) << 28) | (buffer[pos + 1] << 20) | (buffer[pos + 2] << 12) | (buffer[pos + 3] << 4) | (buffer[pos + 4] & 0x0f); pos += 5; } } return result.subarray(0, count); } class ExternalCodec extends _base_ts_1.default { blockContentId; constructor(parameters, dataType) { super(parameters, dataType); this.blockContentId = parameters.blockContentId; if (this.dataType !== 'int' && this.dataType !== 'byte') { throw new errors_ts_1.CramUnimplementedError(`${this.dataType} decoding not yet implemented by EXTERNAL codec`); } } decode(_slice, _coreDataBlock, blocksByContentId, cursors) { if (this.dataType === 'int') { const preDecoded = cursors.preDecodedIntBlocks?.get(this.blockContentId); if (preDecoded) { return preDecoded.values[preDecoded.index++]; } const contentBlock = blocksByContentId[this.blockContentId]; if (!contentBlock) { throw new errors_ts_1.CramMalformedError(`no block found with content ID ${this.blockContentId}`); } const cursor = cursors.externalBlocks.getCursor(this.blockContentId); return (0, util_ts_1.parseItf8)(contentBlock.content, cursor); } else { const contentBlock = blocksByContentId[this.blockContentId]; if (!contentBlock) { throw new errors_ts_1.CramMalformedError(`no block found with content ID ${this.blockContentId}`); } const cursor = cursors.externalBlocks.getCursor(this.blockContentId); if (cursor.bytePosition >= contentBlock.content.length) { throw new errors_ts_1.CramBufferOverrunError('attempted to read beyond end of block. this file seems truncated.'); } return contentBlock.content[cursor.bytePosition++]; } } getBytesSubarray(blocksByContentId, cursors, length) { const { blockContentId } = this.parameters; const contentBlock = blocksByContentId[blockContentId]; if (!contentBlock) { return undefined; } const cursor = cursors.externalBlocks.getCursor(blockContentId); const start = cursor.bytePosition; const end = start + length; if (end > contentBlock.content.length) { throw new errors_ts_1.CramBufferOverrunError('attempted to read beyond end of block. this file seems truncated.'); } cursor.bytePosition = end; return contentBlock.content.subarray(start, end); } } exports.default = ExternalCodec; //# sourceMappingURL=external.js.map