Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
type: new Parser()
.string('key', {
length: 2,
stripNull: false,
// formatter: val => cramPreservationMapKeys[val] || 0,
})
.choice('value', {
tag: 'key',
choices: {
MI: parseByteAsBool,
UI: parseByteAsBool,
PI: parseByteAsBool,
RN: parseByteAsBool,
AP: parseByteAsBool,
RR: parseByteAsBool,
SM: new Parser().array(null, { type: 'uint8', length: 5 }),
TD: new Parser().nest(null, {
type: cramTagDictionary,
formatter: /* istanbul ignore next */ data => data.ents,
}),
},
}),
})
/* istanbul ignore next */
function formatMap(data) {
const map = {}
data.ents.forEach(({ key, value }) => {
if (map[key]) console.warn(`duplicate key ${key} in map`)
map[key] = value
})
return map
.string('key', {
length: 2,
stripNull: false,
// formatter: val => cramPreservationMapKeys[val] || 0,
})
.choice('value', {
tag: 'key',
choices: {
MI: parseByteAsBool,
UI: parseByteAsBool,
PI: parseByteAsBool,
RN: parseByteAsBool,
AP: parseByteAsBool,
RR: parseByteAsBool,
SM: new Parser().array(null, { type: 'uint8', length: 5 }),
TD: new Parser().nest(null, {
type: cramTagDictionary,
formatter: /* istanbul ignore next */ data => data.ents,
}),
},
}),
})
/* istanbul ignore next */
function formatMap(data) {
const map = {}
data.ents.forEach(({ key, value }) => {
if (map[key]) console.warn(`duplicate key ${key} in map`)
map[key] = value
})
return map
}
cramCompressionHeader(majorVersion) {
let parser = new Parser()
// TODO: if we want to support CRAM v1, we will need to refactor
// compression header into 2 parts to parse the landmarks,
// like the container header
parser = parser
.nest('preservation', {
type: cramPreservationMap,
formatter: formatMap,
})
.nest('dataSeriesEncoding', {
type: this.cramDataSeriesEncodingMap(majorVersion),
formatter: formatMap,
})
.nest('tagEncoding', {
type: this.cramTagEncodingMap(majorVersion),
formatter: formatMap,
})
cramContainerHeader1(majorVersion) {
let parser = new Parser()
.int32('length') // byte size of the container data (blocks)
.itf8('refSeqId') // reference sequence identifier, -1 for unmapped reads, -2 for multiple reference sequences
.itf8('refSeqStart') // the alignment start position or 0 for unmapped reads
.itf8('alignmentSpan') // the length of the alignment or 0 for unmapped reads
.itf8('numRecords') // number of records in the container
let maxLength = 4 + 5 * 4
if (majorVersion >= 3) {
parser = parser.ltf8('recordCounter') // 1-based sequential index of records in the file/stream.
maxLength += 9
} else if (majorVersion === 2) {
parser = parser.itf8('recordCounter')
maxLength += 5
}
if (majorVersion > 1) {
tag: 'codecId',
choices: {
0: new Parser(), // NULL
1: new Parser().itf8('blockContentId'), // EXTERNAL
2: new Parser().itf8('offset').itf8('M'), // GOLOMB,
// HUFFMAN_INT
3: Parser.start()
.itf8('numCodes')
.array('symbols', { length: 'numCodes', type: singleItf8 })
.itf8('numLengths')
.array('bitLengths', { length: 'numLengths', type: singleItf8 }),
4: Parser.start() // BYTE_ARRAY_LEN
.nest('lengthsEncoding', { type: 'cramEncoding' })
.nest('valuesEncoding', { type: 'cramEncoding' }),
// BYTE_ARRAY_STOP is a little different for CRAM v1
5: new Parser()
.uint8('stopByte')
[majorVersion > 1 ? 'itf8' : 'int']('blockContentId'),
6: new Parser().itf8('offset').itf8('length'), // BETA
7: new Parser().itf8('offset').itf8('K'), // SUBEXP
8: new Parser().itf8('offset').itf8('log2m'), // GOLOMB_RICE
9: new Parser().itf8('offset'), // GAMMA
},
})
return { parser }
},
cramTagEncodingMap(majorVersion) {
return new Parser()
.itf8('mapSize')
.itf8('mapCount')
.array('ents', {
length: 'mapCount',
type: new Parser()
.itf8('key', {
formatter: /* istanbul ignore next */ integerRepresentation =>
/* istanbul ignore next */
String.fromCharCode((integerRepresentation >> 16) & 0xff) +
String.fromCharCode((integerRepresentation >> 8) & 0xff) +
String.fromCharCode(integerRepresentation & 0xff),
})
.nest('value', { type: this.cramEncoding(majorVersion).parser }),
})
},
const { Parser } = require('@gmod/binary-parser')
const singleItf8 = new Parser().itf8()
const cramFileDefinition = {
parser: new Parser()
.string('magic', { length: 4 })
.uint8('majorVersion')
.uint8('minorVersion')
.string('fileId', { length: 20, stripNull: true }),
maxLength: 26,
}
const cramBlockHeader = {
parser: new Parser()
.uint8('compressionMethod', {
formatter: /* istanbul ignore next */ b => {
const method = ['raw', 'gzip', 'bzip2', 'lzma', 'rans'][b]
if (!method)
throw new Error(`compression method number ${b} not implemented`)
return method
},
})
.uint8('contentType', {
formatter: /* istanbul ignore next */ b => {
const type = [
'FILE_HEADER',
'COMPRESSION_HEADER',
'MAPPED_SLICE_HEADER',
'UNMAPPED_SLICE_HEADER', // < only used in cram v1
'EXTERNAL_DATA',
cramEncoding(majorVersion) {
const parser = new Parser()
.namely('cramEncoding')
.itf8('codecId')
.itf8('parametersBytes')
.choice('parameters', {
tag: 'codecId',
choices: {
0: new Parser(), // NULL
1: new Parser().itf8('blockContentId'), // EXTERNAL
2: new Parser().itf8('offset').itf8('M'), // GOLOMB,
// HUFFMAN_INT
3: Parser.start()
.itf8('numCodes')
.array('symbols', { length: 'numCodes', type: singleItf8 })
.itf8('numLengths')
.array('bitLengths', { length: 'numLengths', type: singleItf8 }),
4: Parser.start() // BYTE_ARRAY_LEN
cramEncoding(majorVersion) {
const parser = new Parser()
.namely('cramEncoding')
.itf8('codecId')
.itf8('parametersBytes')
.choice('parameters', {
tag: 'codecId',
choices: {
0: new Parser(), // NULL
1: new Parser().itf8('blockContentId'), // EXTERNAL
2: new Parser().itf8('offset').itf8('M'), // GOLOMB,
// HUFFMAN_INT
3: Parser.start()
.itf8('numCodes')
.array('symbols', { length: 'numCodes', type: singleItf8 })
.itf8('numLengths')
.array('bitLengths', { length: 'numLengths', type: singleItf8 }),
4: Parser.start() // BYTE_ARRAY_LEN
.nest('lengthsEncoding', { type: 'cramEncoding' })
.nest('valuesEncoding', { type: 'cramEncoding' }),
// BYTE_ARRAY_STOP is a little different for CRAM v1
5: new Parser()
.uint8('stopByte')
[majorVersion > 1 ? 'itf8' : 'int']('blockContentId'),
6: new Parser().itf8('offset').itf8('length'), // BETA
unknown.add(type);
res.push(null);
} else res.push(parseV(environment, slice + (i * ks.size) / ax, len / ax, { ax: 1, type: innerType, complexType }));
}
//If debugging, print unexpected types
if (options.debug && unknown.size) setImmediate(() => console.log('unknown types:', [...unknown].join(',')));
return res;
//Otherwise, read a single value
} else if (!types[type].complex) {
//Add options required by type
let opts = { length: len };
if (types[type].opt) for (const key in types[type].opt) opts[key] = types[type].opt[key];
//We pick the necessary function based on data format (stored in types)
let valParser = new Parser().endianess('big')[types[type].func]('value', opts);
const parsed = valParser.parse(data.slice(slice)).result;
return parsed.value;
//Data is complex but did not find axes
} else throw new Error('Complex type ? with only one axis');
}