@gmod/cram 1.6.1 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +2 -1
- package/src/craiIndex.js +180 -0
- package/src/cramFile/codecs/_base.js +49 -0
- package/src/cramFile/codecs/beta.js +23 -0
- package/src/cramFile/codecs/byteArrayLength.js +55 -0
- package/src/cramFile/codecs/byteArrayStop.js +50 -0
- package/src/cramFile/codecs/external.js +54 -0
- package/src/cramFile/codecs/gamma.js +30 -0
- package/src/cramFile/codecs/huffman.js +137 -0
- package/src/cramFile/codecs/index.js +38 -0
- package/src/cramFile/codecs/subexp.js +32 -0
- package/src/cramFile/constants.js +55 -0
- package/src/cramFile/container/compressionScheme.js +144 -0
- package/src/cramFile/container/index.js +119 -0
- package/src/cramFile/file.js +347 -0
- package/src/cramFile/index.js +3 -0
- package/src/cramFile/record.js +337 -0
- package/src/cramFile/sectionParsers.js +379 -0
- package/src/cramFile/slice/decodeRecord.js +362 -0
- package/src/cramFile/slice/index.js +497 -0
- package/src/cramFile/util.js +169 -0
- package/src/errors.js +22 -0
- package/src/index.js +5 -0
- package/src/indexedCramFile.js +191 -0
- package/src/io/bufferCache.js +66 -0
- package/src/io/index.js +26 -0
- package/src/io/localFile.js +35 -0
- package/src/io/remoteFile.js +71 -0
- package/src/rans/README.md +1 -0
- package/src/rans/constants.js +5 -0
- package/src/rans/d04.js +83 -0
- package/src/rans/d14.js +59 -0
- package/src/rans/decoding.js +141 -0
- package/src/rans/frequencies.js +121 -0
- package/src/rans/index.js +249 -0
- package/src/sam.js +15 -0
- package/src/unzip-pako.ts +5 -0
- package/src/unzip.ts +2 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { CramMalformedError } from '../errors'
|
|
2
|
+
|
|
3
|
+
import { TOTFREQ } from './constants'
|
|
4
|
+
import Decoding from './decoding'
|
|
5
|
+
|
|
6
|
+
function assert(result) {
|
|
7
|
+
if (!result) {
|
|
8
|
+
throw new CramMalformedError('assertion failed')
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function readStatsO0(
|
|
13
|
+
/* ByteBuffer */ cp,
|
|
14
|
+
/* Decoding.AriDecoder */ decoder,
|
|
15
|
+
/* Decoding.RansDecSymbol[] */ syms,
|
|
16
|
+
) {
|
|
17
|
+
// Pre-compute reverse lookup of frequency.
|
|
18
|
+
let rle = 0
|
|
19
|
+
let x = 0
|
|
20
|
+
let j = cp.get() & 0xff
|
|
21
|
+
do {
|
|
22
|
+
if (decoder.fc[j] == null) {
|
|
23
|
+
decoder.fc[j] = new Decoding.FC()
|
|
24
|
+
}
|
|
25
|
+
decoder.fc[j].F = cp.get() & 0xff
|
|
26
|
+
if (decoder.fc[j].F >= 128) {
|
|
27
|
+
decoder.fc[j].F &= ~128
|
|
28
|
+
decoder.fc[j].F = ((decoder.fc[j].F & 127) << 8) | (cp.get() & 0xff)
|
|
29
|
+
}
|
|
30
|
+
decoder.fc[j].C = x
|
|
31
|
+
|
|
32
|
+
Decoding.symbolInit(syms[j], decoder.fc[j].C, decoder.fc[j].F)
|
|
33
|
+
|
|
34
|
+
/* Build reverse lookup table */
|
|
35
|
+
if (!decoder.R) {
|
|
36
|
+
decoder.R = new Array(TOTFREQ)
|
|
37
|
+
}
|
|
38
|
+
decoder.R.fill(j, x, x + decoder.fc[j].F)
|
|
39
|
+
|
|
40
|
+
x += decoder.fc[j].F
|
|
41
|
+
|
|
42
|
+
if (rle === 0 && j + 1 === (0xff & cp.getByteAt(cp.position()))) {
|
|
43
|
+
j = cp.get() & 0xff
|
|
44
|
+
rle = cp.get() & 0xff
|
|
45
|
+
} else if (rle !== 0) {
|
|
46
|
+
rle -= 1
|
|
47
|
+
j += 1
|
|
48
|
+
} else {
|
|
49
|
+
j = cp.get() & 0xff
|
|
50
|
+
}
|
|
51
|
+
} while (j !== 0)
|
|
52
|
+
|
|
53
|
+
assert(x < TOTFREQ)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function readStatsO1(
|
|
57
|
+
/* ByteBuffer */ cp,
|
|
58
|
+
/* Decoding.AriDecoder[] */ D,
|
|
59
|
+
/* Decoding.RansDecSymbol[][] */ syms,
|
|
60
|
+
) {
|
|
61
|
+
let rlei = 0
|
|
62
|
+
let i = 0xff & cp.get()
|
|
63
|
+
do {
|
|
64
|
+
let rlej = 0
|
|
65
|
+
let x = 0
|
|
66
|
+
let j = 0xff & cp.get()
|
|
67
|
+
if (D[i] == null) {
|
|
68
|
+
D[i] = new Decoding.AriDecoder()
|
|
69
|
+
}
|
|
70
|
+
do {
|
|
71
|
+
if (D[i].fc[j] == null) {
|
|
72
|
+
D[i].fc[j] = new Decoding.FC()
|
|
73
|
+
}
|
|
74
|
+
D[i].fc[j].F = 0xff & cp.get()
|
|
75
|
+
if (D[i].fc[j].F >= 128) {
|
|
76
|
+
D[i].fc[j].F &= ~128
|
|
77
|
+
D[i].fc[j].F = ((D[i].fc[j].F & 127) << 8) | (0xff & cp.get())
|
|
78
|
+
}
|
|
79
|
+
D[i].fc[j].C = x
|
|
80
|
+
|
|
81
|
+
if (D[i].fc[j].F === 0) {
|
|
82
|
+
D[i].fc[j].F = TOTFREQ
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (syms[i][j] == null) {
|
|
86
|
+
syms[i][j] = new Decoding.RansDecSymbol()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
Decoding.symbolInit(syms[i][j], D[i].fc[j].C, D[i].fc[j].F)
|
|
90
|
+
|
|
91
|
+
/* Build reverse lookup table */
|
|
92
|
+
if (D[i].R == null) {
|
|
93
|
+
D[i].R = new Array(TOTFREQ)
|
|
94
|
+
}
|
|
95
|
+
D[i].R.fill(j, x, x + D[i].fc[j].F)
|
|
96
|
+
|
|
97
|
+
x += D[i].fc[j].F
|
|
98
|
+
assert(x <= TOTFREQ)
|
|
99
|
+
|
|
100
|
+
if (rlej === 0 && j + 1 === (0xff & cp.getByteAt(cp.position()))) {
|
|
101
|
+
j = 0xff & cp.get()
|
|
102
|
+
rlej = 0xff & cp.get()
|
|
103
|
+
} else if (rlej !== 0) {
|
|
104
|
+
rlej -= 1
|
|
105
|
+
j += 1
|
|
106
|
+
} else {
|
|
107
|
+
j = 0xff & cp.get()
|
|
108
|
+
}
|
|
109
|
+
} while (j !== 0)
|
|
110
|
+
|
|
111
|
+
if (rlei === 0 && i + 1 === (0xff & cp.getByteAt(cp.position()))) {
|
|
112
|
+
i = 0xff & cp.get()
|
|
113
|
+
rlei = 0xff & cp.get()
|
|
114
|
+
} else if (rlei !== 0) {
|
|
115
|
+
rlei -= 1
|
|
116
|
+
i += 1
|
|
117
|
+
} else {
|
|
118
|
+
i = 0xff & cp.get()
|
|
119
|
+
}
|
|
120
|
+
} while (i !== 0)
|
|
121
|
+
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { CramMalformedError } from '../errors'
|
|
2
|
+
|
|
3
|
+
import Decoding from './decoding'
|
|
4
|
+
import { readStatsO0, readStatsO1 } from './frequencies'
|
|
5
|
+
|
|
6
|
+
import D04 from './d04'
|
|
7
|
+
import D14 from './d14'
|
|
8
|
+
|
|
9
|
+
// const /* int */ ORDER_BYTE_LENGTH = 1
|
|
10
|
+
// const /* int */ COMPRESSED_BYTE_LENGTH = 4
|
|
11
|
+
const /* int */ RAW_BYTE_LENGTH = 4
|
|
12
|
+
// const /* int */ PREFIX_BYTE_LENGTH =
|
|
13
|
+
// ORDER_BYTE_LENGTH + COMPRESSED_BYTE_LENGTH + RAW_BYTE_LENGTH
|
|
14
|
+
|
|
15
|
+
// enum ORDER {
|
|
16
|
+
// ZERO, ONE;
|
|
17
|
+
|
|
18
|
+
// static ORDER fromInt(const /* int */ value) {
|
|
19
|
+
// try {
|
|
20
|
+
// return ORDER.values()[value];
|
|
21
|
+
// } catch (const ArrayIndexOutOfBoundsException e) {
|
|
22
|
+
// throw new RuntimeException("Unknown rANS order: " + value);
|
|
23
|
+
// }
|
|
24
|
+
// }
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
// static ByteBuffer compress(const ByteBuffer input, const ORDER order, const ByteBuffer out) {
|
|
28
|
+
// if (input.remaining() == 0)
|
|
29
|
+
// return EMPTY_BUFFER;
|
|
30
|
+
|
|
31
|
+
// if (input.remaining() < 4)
|
|
32
|
+
// return encode_order0_way4(input, out);
|
|
33
|
+
|
|
34
|
+
// switch (order) {
|
|
35
|
+
// case ZERO:
|
|
36
|
+
// return encode_order0_way4(input, out);
|
|
37
|
+
// case ONE:
|
|
38
|
+
// return encode_order1_way4(input, out);
|
|
39
|
+
|
|
40
|
+
// default:
|
|
41
|
+
// throw new RuntimeException("Unknown rANS order: " + order);
|
|
42
|
+
// }
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
// static /* ByteBuffer */ allocateIfNeeded(/* const int */ in_size,
|
|
46
|
+
// /* const ByteBuffer */ out_buf) {
|
|
47
|
+
// const /* int */ compressedSize = (/* int */) (1.05 * in_size + 257 * 257 * 3 + 4);
|
|
48
|
+
// if (out_buf == null)
|
|
49
|
+
// return ByteBuffer.allocate(compressedSize);
|
|
50
|
+
// if (out_buf.remaining() < compressedSize)
|
|
51
|
+
// throw new RuntimeException("Insufficient buffer size.");
|
|
52
|
+
// out_buf.order(ByteOrder.LITTLE_ENDIAN);
|
|
53
|
+
// return out_buf;
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// static ByteBuffer encode_order0_way4(const ByteBuffer input,
|
|
57
|
+
// ByteBuffer out_buf) {
|
|
58
|
+
// const /* int */ in_size = input.remaining();
|
|
59
|
+
// out_buf = allocateIfNeeded(in_size, out_buf);
|
|
60
|
+
// const /* int */ freqTableStart = PREFIX_BYTE_LENGTH;
|
|
61
|
+
// out_buf.position(freqTableStart);
|
|
62
|
+
|
|
63
|
+
// const /* int */[] F = Frequencies.calcFrequencies_o0(in);
|
|
64
|
+
// const RansEncSymbol[] syms = Frequencies.buildSyms_o0(F);
|
|
65
|
+
|
|
66
|
+
// const ByteBuffer cp = out_buf.slice();
|
|
67
|
+
// const /* int */ frequencyTable_size = Frequencies.writeFrequencies_o0(cp, F);
|
|
68
|
+
|
|
69
|
+
// input.rewind();
|
|
70
|
+
// const /* int */ compressedBlob_size = E04.compress(input, syms, cp);
|
|
71
|
+
|
|
72
|
+
// finalizeCompressed(0, out_buf, in_size, frequencyTable_size,
|
|
73
|
+
// compressedBlob_size);
|
|
74
|
+
// return out_buf;
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
// static ByteBuffer encode_order1_way4(const ByteBuffer input,
|
|
78
|
+
// ByteBuffer out_buf) {
|
|
79
|
+
// const /* int */ in_size = input.remaining();
|
|
80
|
+
// out_buf = allocateIfNeeded(in_size, out_buf);
|
|
81
|
+
// const /* int */ freqTableStart = PREFIX_BYTE_LENGTH;
|
|
82
|
+
// out_buf.position(freqTableStart);
|
|
83
|
+
|
|
84
|
+
// const /* int */[][] F = Frequencies.calcFrequencies_o1(in);
|
|
85
|
+
// const RansEncSymbol[][] syms = Frequencies.buildSyms_o1(F);
|
|
86
|
+
|
|
87
|
+
// const ByteBuffer cp = out_buf.slice();
|
|
88
|
+
// const /* int */ frequencyTable_size = Frequencies.writeFrequencies_o1(cp, F);
|
|
89
|
+
|
|
90
|
+
// input.rewind();
|
|
91
|
+
// const /* int */ compressedBlob_size = E14.compress(input, syms, cp);
|
|
92
|
+
|
|
93
|
+
// finalizeCompressed(1, out_buf, in_size, frequencyTable_size,
|
|
94
|
+
// compressedBlob_size);
|
|
95
|
+
// return out_buf;
|
|
96
|
+
// }
|
|
97
|
+
|
|
98
|
+
// static void finalizeCompressed(const /* int */ order, const ByteBuffer out_buf,
|
|
99
|
+
// const /* int */ in_size, const /* int */ frequencyTable_size, const /* int */ compressedBlob_size) {
|
|
100
|
+
// out_buf.limit(PREFIX_BYTE_LENGTH + frequencyTable_size
|
|
101
|
+
// + compressedBlob_size);
|
|
102
|
+
// out_buf.put(0, (byte) order);
|
|
103
|
+
// out_buf.order(ByteOrder.LITTLE_ENDIAN);
|
|
104
|
+
// const /* int */ compressedSizeOffset = ORDER_BYTE_LENGTH;
|
|
105
|
+
// out_buf.putInt(compressedSizeOffset, frequencyTable_size
|
|
106
|
+
// + compressedBlob_size);
|
|
107
|
+
// const /* int */ rawSizeOffset = ORDER_BYTE_LENGTH + COMPRESSED_BYTE_LENGTH;
|
|
108
|
+
// out_buf.putInt(rawSizeOffset, in_size);
|
|
109
|
+
// out_buf.rewind();
|
|
110
|
+
// }
|
|
111
|
+
|
|
112
|
+
function /* static ByteBuffer */ uncompressOrder0Way4(
|
|
113
|
+
/* const ByteBuffer */ input,
|
|
114
|
+
/* const ByteBuffer */ out,
|
|
115
|
+
) {
|
|
116
|
+
// input.order(ByteOrder.LITTLE_ENDIAN);
|
|
117
|
+
const D = new Decoding.AriDecoder()
|
|
118
|
+
const syms = new Array(256)
|
|
119
|
+
for (let i = 0; i < syms.length; i += 1) {
|
|
120
|
+
syms[i] = new Decoding.Symbol()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
readStatsO0(input, D, syms)
|
|
124
|
+
|
|
125
|
+
D04(input, D, syms, out)
|
|
126
|
+
|
|
127
|
+
return out
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function /* static ByteBuffer */ uncompressOrder1Way4(
|
|
131
|
+
/* const ByteBuffer */ input,
|
|
132
|
+
/* const ByteBuffer */ output,
|
|
133
|
+
) {
|
|
134
|
+
const D = new Array(256)
|
|
135
|
+
for (let i = 0; i < D.length; i += 1) {
|
|
136
|
+
D[i] = new Decoding.AriDecoder()
|
|
137
|
+
}
|
|
138
|
+
const /* Decoding.RansDecSymbol[][] */ syms = new Array(256)
|
|
139
|
+
for (let i = 0; i < syms.length; i += 1) {
|
|
140
|
+
syms[i] = new Array(256)
|
|
141
|
+
for (let j = 0; j < syms[i].length; j += 1) {
|
|
142
|
+
syms[i][j] = new Decoding.Symbol()
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
readStatsO1(input, D, syms)
|
|
146
|
+
|
|
147
|
+
D14(input, output, D, syms)
|
|
148
|
+
|
|
149
|
+
return output
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* compat layer to make a node buffer act like a java ByteBuffer */
|
|
153
|
+
class ByteBuffer {
|
|
154
|
+
constructor(nodeBuffer, initialInputPosition = 0) {
|
|
155
|
+
this._buffer = nodeBuffer
|
|
156
|
+
this._position = initialInputPosition
|
|
157
|
+
this.length = nodeBuffer.length
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get() {
|
|
161
|
+
const b = this._buffer[this._position]
|
|
162
|
+
this._position += 1
|
|
163
|
+
return b
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
getByte() {
|
|
167
|
+
return this.get()
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
getByteAt(position) {
|
|
171
|
+
return this._buffer[position]
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
position() {
|
|
175
|
+
return this._position
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
put(val) {
|
|
179
|
+
this._buffer[this._position] = val
|
|
180
|
+
this._position += 1
|
|
181
|
+
return val
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
putAt(position, val) {
|
|
185
|
+
this._buffer[position] = val
|
|
186
|
+
return val
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
setPosition(pos) {
|
|
190
|
+
this._position = pos
|
|
191
|
+
return pos
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
getInt() {
|
|
195
|
+
const i = this._buffer.readInt32LE(this._position)
|
|
196
|
+
this._position += 4
|
|
197
|
+
return i
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
remaining() {
|
|
201
|
+
return this._buffer.length - this._position
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// static /* const */ ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
|
|
206
|
+
export default function uncompress(
|
|
207
|
+
inputBuffer,
|
|
208
|
+
outputBuffer,
|
|
209
|
+
initialInputPosition = 0,
|
|
210
|
+
) {
|
|
211
|
+
if (inputBuffer.length === 0) {
|
|
212
|
+
outputBuffer.fill(0)
|
|
213
|
+
return outputBuffer
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const input = new ByteBuffer(inputBuffer, initialInputPosition)
|
|
217
|
+
// input.order(ByteOrder.LITTLE_ENDIAN);
|
|
218
|
+
|
|
219
|
+
const order = input.get()
|
|
220
|
+
if (order !== 0 && order !== 1) {
|
|
221
|
+
throw new CramMalformedError(`Invalid rANS order ${order}`)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const /* int */ inputSize = input.getInt()
|
|
225
|
+
if (inputSize !== input.remaining() - RAW_BYTE_LENGTH) {
|
|
226
|
+
throw new CramMalformedError('Incorrect input length.')
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const /* int */ outputSize = input.getInt()
|
|
230
|
+
const output = new ByteBuffer(outputBuffer || Buffer.allocUnsafe(outputSize))
|
|
231
|
+
// TODO output.limit(outputSize)
|
|
232
|
+
|
|
233
|
+
if (output.length < outputSize) {
|
|
234
|
+
throw new CramMalformedError(
|
|
235
|
+
`Output buffer too small to fit ${outputSize} bytes.`,
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
switch (order) {
|
|
240
|
+
case 0:
|
|
241
|
+
return uncompressOrder0Way4(input, output)
|
|
242
|
+
|
|
243
|
+
case 1:
|
|
244
|
+
return uncompressOrder1Way4(input, output)
|
|
245
|
+
|
|
246
|
+
default:
|
|
247
|
+
throw new CramMalformedError(`Invalid rANS order: ${order}`)
|
|
248
|
+
}
|
|
249
|
+
}
|
package/src/sam.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function parseHeaderText(text) {
|
|
2
|
+
const lines = text.split(/\r?\n/)
|
|
3
|
+
const data = []
|
|
4
|
+
lines.forEach(line => {
|
|
5
|
+
const [tag, ...fields] = line.split(/\t/)
|
|
6
|
+
const parsedFields = fields.map(f => {
|
|
7
|
+
const [fieldTag, value] = f.split(':', 2)
|
|
8
|
+
return { tag: fieldTag, value }
|
|
9
|
+
})
|
|
10
|
+
if (tag) {
|
|
11
|
+
data.push({ tag: tag.substr(1), data: parsedFields })
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
return data
|
|
15
|
+
}
|
package/src/unzip.ts
ADDED