@gmod/tabix 1.5.13 → 1.5.15
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 +13 -2
- package/README.md +9 -0
- package/dist/chunk.js +0 -1
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +1 -2
- package/dist/csi.js +10 -10
- package/dist/csi.js.map +1 -1
- package/dist/indexFile.js +8 -8
- package/dist/indexFile.js.map +1 -1
- package/dist/tabix-bundle.js +2 -0
- package/dist/tabix-bundle.js.LICENSE.txt +8 -0
- package/dist/tabixIndexedFile.d.ts +43 -21
- package/dist/tabixIndexedFile.js +82 -58
- package/dist/tabixIndexedFile.js.map +1 -1
- package/dist/tbi.d.ts +0 -1
- package/dist/tbi.js +12 -11
- package/dist/tbi.js.map +1 -1
- package/dist/util.d.ts +7 -7
- package/dist/util.js +11 -12
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.d.ts +0 -2
- package/dist/virtualOffset.js +1 -15
- package/dist/virtualOffset.js.map +1 -1
- package/esm/chunk.js +0 -1
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +1 -2
- package/esm/csi.js +4 -4
- package/esm/csi.js.map +1 -1
- package/esm/indexFile.js +1 -1
- package/esm/indexFile.js.map +1 -1
- package/esm/tabixIndexedFile.d.ts +43 -21
- package/esm/tabixIndexedFile.js +68 -44
- package/esm/tabixIndexedFile.js.map +1 -1
- package/esm/tbi.d.ts +0 -1
- package/esm/tbi.js +6 -5
- package/esm/tbi.js.map +1 -1
- package/esm/util.d.ts +7 -7
- package/esm/util.js +6 -6
- package/esm/util.js.map +1 -1
- package/esm/virtualOffset.d.ts +0 -2
- package/esm/virtualOffset.js +0 -13
- package/esm/virtualOffset.js.map +1 -1
- package/package.json +25 -21
- package/src/chunk.ts +1 -1
- package/src/csi.ts +6 -5
- package/src/indexFile.ts +1 -1
- package/src/tabixIndexedFile.ts +74 -52
- package/src/tbi.ts +7 -6
- package/src/util.ts +7 -7
- package/src/virtualOffset.ts +7 -21
package/src/tabixIndexedFile.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import AbortablePromiseCache from 'abortable-promise-cache'
|
|
1
|
+
import AbortablePromiseCache from '@gmod/abortable-promise-cache'
|
|
2
2
|
import LRU from 'quick-lru'
|
|
3
3
|
import { Buffer } from 'buffer'
|
|
4
|
-
import { GenericFilehandle, LocalFile } from 'generic-filehandle'
|
|
4
|
+
import { GenericFilehandle, RemoteFile, LocalFile } from 'generic-filehandle'
|
|
5
5
|
import { unzip, unzipChunkSlice } from '@gmod/bgzf-filehandle'
|
|
6
6
|
import { checkAbortSignal } from './util'
|
|
7
7
|
import IndexFile, { Options, IndexData } from './indexFile'
|
|
@@ -33,44 +33,57 @@ function timeout(time: number) {
|
|
|
33
33
|
export default class TabixIndexedFile {
|
|
34
34
|
private filehandle: GenericFilehandle
|
|
35
35
|
private index: IndexFile
|
|
36
|
-
private chunkSizeLimit: number
|
|
37
36
|
private yieldTime: number
|
|
38
37
|
private renameRefSeq: (n: string) => string
|
|
39
38
|
private chunkCache: AbortablePromiseCache<Chunk, ReadChunk>
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
41
|
* @param {object} args
|
|
42
|
+
*
|
|
43
43
|
* @param {string} [args.path]
|
|
44
|
+
*
|
|
44
45
|
* @param {filehandle} [args.filehandle]
|
|
46
|
+
*
|
|
45
47
|
* @param {string} [args.tbiPath]
|
|
48
|
+
*
|
|
46
49
|
* @param {filehandle} [args.tbiFilehandle]
|
|
50
|
+
*
|
|
47
51
|
* @param {string} [args.csiPath]
|
|
52
|
+
*
|
|
48
53
|
* @param {filehandle} [args.csiFilehandle]
|
|
49
|
-
*
|
|
50
|
-
* @param {
|
|
51
|
-
*
|
|
52
|
-
*
|
|
54
|
+
*
|
|
55
|
+
* @param {number} [args.yieldTime] yield to main thread after N milliseconds
|
|
56
|
+
* if reading features is taking a long time to avoid hanging main thread
|
|
57
|
+
*
|
|
58
|
+
* @param {function} [args.renameRefSeqs] optional function with sig `string
|
|
59
|
+
* => string` to transform reference sequence names for the purpose of
|
|
60
|
+
* indexing and querying. note that the data that is returned is not altered,
|
|
61
|
+
* just the names of the reference sequences that are used for querying.
|
|
53
62
|
*/
|
|
54
63
|
constructor({
|
|
55
64
|
path,
|
|
56
65
|
filehandle,
|
|
66
|
+
url,
|
|
57
67
|
tbiPath,
|
|
68
|
+
tbiUrl,
|
|
58
69
|
tbiFilehandle,
|
|
59
70
|
csiPath,
|
|
71
|
+
csiUrl,
|
|
60
72
|
csiFilehandle,
|
|
61
73
|
yieldTime = 500,
|
|
62
|
-
chunkSizeLimit = 50000000,
|
|
63
74
|
renameRefSeqs = n => n,
|
|
64
75
|
chunkCacheSize = 5 * 2 ** 20,
|
|
65
76
|
}: {
|
|
66
77
|
path?: string
|
|
67
78
|
filehandle?: GenericFilehandle
|
|
79
|
+
url?: string
|
|
68
80
|
tbiPath?: string
|
|
81
|
+
tbiUrl?: string
|
|
69
82
|
tbiFilehandle?: GenericFilehandle
|
|
70
83
|
csiPath?: string
|
|
84
|
+
csiUrl?: string
|
|
71
85
|
csiFilehandle?: GenericFilehandle
|
|
72
86
|
yieldTime?: number
|
|
73
|
-
chunkSizeLimit?: number
|
|
74
87
|
renameRefSeqs?: (n: string) => string
|
|
75
88
|
chunkCacheSize?: number
|
|
76
89
|
}) {
|
|
@@ -78,6 +91,8 @@ export default class TabixIndexedFile {
|
|
|
78
91
|
this.filehandle = filehandle
|
|
79
92
|
} else if (path) {
|
|
80
93
|
this.filehandle = new LocalFile(path)
|
|
94
|
+
} else if (url) {
|
|
95
|
+
this.filehandle = new RemoteFile(url)
|
|
81
96
|
} else {
|
|
82
97
|
throw new TypeError('must provide either filehandle or path')
|
|
83
98
|
}
|
|
@@ -107,13 +122,24 @@ export default class TabixIndexedFile {
|
|
|
107
122
|
filehandle: new LocalFile(`${path}.tbi`),
|
|
108
123
|
renameRefSeqs,
|
|
109
124
|
})
|
|
125
|
+
} else if (csiUrl) {
|
|
126
|
+
this.index = new CSI({
|
|
127
|
+
filehandle: new RemoteFile(csiUrl),
|
|
128
|
+
})
|
|
129
|
+
} else if (tbiUrl) {
|
|
130
|
+
this.index = new TBI({
|
|
131
|
+
filehandle: new RemoteFile(tbiUrl),
|
|
132
|
+
})
|
|
133
|
+
} else if (url) {
|
|
134
|
+
this.index = new TBI({
|
|
135
|
+
filehandle: new RemoteFile(`${url}.tbi`),
|
|
136
|
+
})
|
|
110
137
|
} else {
|
|
111
138
|
throw new TypeError(
|
|
112
|
-
'must provide one of tbiFilehandle, tbiPath, csiFilehandle,
|
|
139
|
+
'must provide one of tbiFilehandle, tbiPath, csiFilehandle, csiPath, tbiUrl, csiUrl',
|
|
113
140
|
)
|
|
114
141
|
}
|
|
115
142
|
|
|
116
|
-
this.chunkSizeLimit = chunkSizeLimit
|
|
117
143
|
this.renameRefSeq = renameRefSeqs
|
|
118
144
|
this.yieldTime = yieldTime
|
|
119
145
|
this.chunkCache = new AbortablePromiseCache<Chunk, ReadChunk>({
|
|
@@ -125,10 +151,16 @@ export default class TabixIndexedFile {
|
|
|
125
151
|
|
|
126
152
|
/**
|
|
127
153
|
* @param refName name of the reference sequence
|
|
154
|
+
*
|
|
128
155
|
* @param start start of the region (in 0-based half-open coordinates)
|
|
156
|
+
*
|
|
129
157
|
* @param end end of the region (in 0-based half-open coordinates)
|
|
130
|
-
*
|
|
131
|
-
* @
|
|
158
|
+
*
|
|
159
|
+
* @param opts callback called for each line in the region. can also pass a
|
|
160
|
+
* object param containing obj.lineCallback, obj.signal, etc
|
|
161
|
+
*
|
|
162
|
+
* @returns promise that is resolved when the whole read is finished,
|
|
163
|
+
* rejected on error
|
|
132
164
|
*/
|
|
133
165
|
async getLines(
|
|
134
166
|
refName: string,
|
|
@@ -139,9 +171,7 @@ export default class TabixIndexedFile {
|
|
|
139
171
|
let signal: AbortSignal | undefined
|
|
140
172
|
let options: Options = {}
|
|
141
173
|
let callback: (line: string, lineOffset: number) => void
|
|
142
|
-
|
|
143
|
-
throw new TypeError('line callback must be provided')
|
|
144
|
-
}
|
|
174
|
+
|
|
145
175
|
if (typeof opts === 'function') {
|
|
146
176
|
callback = opts
|
|
147
177
|
} else {
|
|
@@ -149,12 +179,6 @@ export default class TabixIndexedFile {
|
|
|
149
179
|
callback = opts.lineCallback
|
|
150
180
|
signal = opts.signal
|
|
151
181
|
}
|
|
152
|
-
if (refName === undefined) {
|
|
153
|
-
throw new TypeError('must provide a reference sequence name')
|
|
154
|
-
}
|
|
155
|
-
if (!callback) {
|
|
156
|
-
throw new TypeError('line callback must be provided')
|
|
157
|
-
}
|
|
158
182
|
|
|
159
183
|
const metadata = await this.index.getMetadata(options)
|
|
160
184
|
checkAbortSignal(signal)
|
|
@@ -172,17 +196,6 @@ export default class TabixIndexedFile {
|
|
|
172
196
|
const chunks = await this.index.blocksForRange(refName, start, end, options)
|
|
173
197
|
checkAbortSignal(signal)
|
|
174
198
|
|
|
175
|
-
// check the chunks for any that are over the size limit. if
|
|
176
|
-
// any are, don't fetch any of them
|
|
177
|
-
for (const chunk of chunks) {
|
|
178
|
-
const size = chunk.fetchedSize()
|
|
179
|
-
if (size > this.chunkSizeLimit) {
|
|
180
|
-
throw new Error(
|
|
181
|
-
`Too much data. Chunk size ${size.toLocaleString()} bytes exceeds chunkSizeLimit of ${this.chunkSizeLimit.toLocaleString()}.`,
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
199
|
// now go through each chunk and parse and filter the lines out of it
|
|
187
200
|
let last = Date.now()
|
|
188
201
|
for (const c of chunks) {
|
|
@@ -204,8 +217,9 @@ export default class TabixIndexedFile {
|
|
|
204
217
|
const b = buffer.slice(blockStart, n)
|
|
205
218
|
const line = decoder?.decode(b) ?? b.toString()
|
|
206
219
|
|
|
220
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
207
221
|
if (dpositions) {
|
|
208
|
-
while (blockStart + c.minv.dataPosition >= dpositions[pos++]) {}
|
|
222
|
+
while (blockStart + c.minv.dataPosition >= dpositions[pos++]!) {}
|
|
209
223
|
pos--
|
|
210
224
|
}
|
|
211
225
|
|
|
@@ -242,8 +256,8 @@ export default class TabixIndexedFile {
|
|
|
242
256
|
// then the blockStart-dpositions is an uncompressed file offset from
|
|
243
257
|
// that bgzip block boundary, and since the cpositions are multiplied by
|
|
244
258
|
// (1 << 8) these uncompressed offsets get a unique space
|
|
245
|
-
cpositions[pos] * (1 << 8) +
|
|
246
|
-
(blockStart - dpositions[pos]) +
|
|
259
|
+
cpositions[pos]! * (1 << 8) +
|
|
260
|
+
(blockStart - dpositions[pos]!) +
|
|
247
261
|
c.minv.dataPosition +
|
|
248
262
|
1,
|
|
249
263
|
)
|
|
@@ -270,14 +284,15 @@ export default class TabixIndexedFile {
|
|
|
270
284
|
}
|
|
271
285
|
|
|
272
286
|
/**
|
|
273
|
-
* get a buffer containing the "header" region of
|
|
274
|
-
*
|
|
275
|
-
* non-meta line
|
|
287
|
+
* get a buffer containing the "header" region of the file, which are the
|
|
288
|
+
* bytes up to the first non-meta line
|
|
276
289
|
*/
|
|
277
290
|
async getHeaderBuffer(opts: Options = {}) {
|
|
278
291
|
const { firstDataLine, metaChar, maxBlockSize } =
|
|
279
292
|
await this.getMetadata(opts)
|
|
280
293
|
checkAbortSignal(opts.signal)
|
|
294
|
+
|
|
295
|
+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
281
296
|
const maxFetch = (firstDataLine?.blockPosition || 0) + maxBlockSize
|
|
282
297
|
// TODO: what if we don't have a firstDataLine, and the header
|
|
283
298
|
// actually takes up more than one block? this case is not covered here
|
|
@@ -305,8 +320,8 @@ export default class TabixIndexedFile {
|
|
|
305
320
|
}
|
|
306
321
|
|
|
307
322
|
/**
|
|
308
|
-
* get a string containing the "header" region of the
|
|
309
|
-
*
|
|
323
|
+
* get a string containing the "header" region of the file, is the portion up
|
|
324
|
+
* to the first non-meta line
|
|
310
325
|
*
|
|
311
326
|
* @returns {Promise} for a string
|
|
312
327
|
*/
|
|
@@ -316,9 +331,8 @@ export default class TabixIndexedFile {
|
|
|
316
331
|
}
|
|
317
332
|
|
|
318
333
|
/**
|
|
319
|
-
* get an array of reference sequence names, in the order in which
|
|
320
|
-
*
|
|
321
|
-
* to these names.
|
|
334
|
+
* get an array of reference sequence names, in the order in which they occur
|
|
335
|
+
* in the file. reference sequence renaming is not applied to these names.
|
|
322
336
|
*/
|
|
323
337
|
async getReferenceSequenceNames(opts: Options = {}) {
|
|
324
338
|
const metadata = await this.getMetadata(opts)
|
|
@@ -326,12 +340,17 @@ export default class TabixIndexedFile {
|
|
|
326
340
|
}
|
|
327
341
|
|
|
328
342
|
/**
|
|
329
|
-
* @param {object} metadata metadata object from the parsed index,
|
|
330
|
-
*
|
|
343
|
+
* @param {object} metadata metadata object from the parsed index, containing
|
|
344
|
+
* columnNumbers, metaChar, and format
|
|
345
|
+
*
|
|
331
346
|
* @param {string} regionRefName
|
|
347
|
+
*
|
|
332
348
|
* @param {number} regionStart region start coordinate (0-based-half-open)
|
|
349
|
+
*
|
|
333
350
|
* @param {number} regionEnd region end coordinate (0-based-half-open)
|
|
351
|
+
*
|
|
334
352
|
* @param {array[string]} line
|
|
353
|
+
*
|
|
335
354
|
* @returns {object} like `{startCoordinate, overlaps}`. overlaps is boolean,
|
|
336
355
|
* true if line is a data line that overlaps the given region
|
|
337
356
|
*/
|
|
@@ -364,9 +383,9 @@ export default class TabixIndexedFile {
|
|
|
364
383
|
}
|
|
365
384
|
const maxColumn = Math.max(ref, start, end)
|
|
366
385
|
|
|
367
|
-
// this code is kind of complex, but it is fairly fast.
|
|
368
|
-
//
|
|
369
|
-
//
|
|
386
|
+
// this code is kind of complex, but it is fairly fast. basically, we want
|
|
387
|
+
// to avoid doing a split, because if the lines are really long that could
|
|
388
|
+
// lead to us allocating a bunch of extra memory, which is slow
|
|
370
389
|
|
|
371
390
|
let currentColumnNumber = 1 // cols are numbered starting at 1 in the index metadata
|
|
372
391
|
let currentColumnStart = 0
|
|
@@ -450,8 +469,11 @@ export default class TabixIndexedFile {
|
|
|
450
469
|
}
|
|
451
470
|
|
|
452
471
|
/**
|
|
453
|
-
* return the approximate number of data lines in the given reference
|
|
472
|
+
* return the approximate number of data lines in the given reference
|
|
473
|
+
* sequence
|
|
474
|
+
*
|
|
454
475
|
* @param refSeq reference sequence name
|
|
476
|
+
*
|
|
455
477
|
* @returns number of data lines present on that reference sequence
|
|
456
478
|
*/
|
|
457
479
|
async lineCount(refName: string, opts: Options = {}) {
|
|
@@ -476,8 +498,8 @@ export default class TabixIndexedFile {
|
|
|
476
498
|
* contiguous bgzip blocks) of the file
|
|
477
499
|
*/
|
|
478
500
|
async readChunk(c: Chunk, opts: Options = {}) {
|
|
479
|
-
// fetch the uncompressed data, uncompress carefully a block at a time,
|
|
480
|
-
//
|
|
501
|
+
// fetch the uncompressed data, uncompress carefully a block at a time, and
|
|
502
|
+
// stop when done
|
|
481
503
|
|
|
482
504
|
const data = await this._readRegion(
|
|
483
505
|
c.minv.blockPosition,
|
package/src/tbi.ts
CHANGED
|
@@ -10,7 +10,8 @@ const TBI_MAGIC = 21578324 // TBI\1
|
|
|
10
10
|
const TAD_LIDX_SHIFT = 14
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* calculate the list of bins that may overlap with region [beg,end)
|
|
13
|
+
* calculate the list of bins that may overlap with region [beg,end)
|
|
14
|
+
* (zero-based half-open)
|
|
14
15
|
*/
|
|
15
16
|
function reg2bins(beg: number, end: number) {
|
|
16
17
|
beg += 1 // < convert to 1-based closed
|
|
@@ -22,16 +23,16 @@ function reg2bins(beg: number, end: number) {
|
|
|
22
23
|
[73 + (beg >> 20), 73 + (end >> 20)],
|
|
23
24
|
[585 + (beg >> 17), 585 + (end >> 17)],
|
|
24
25
|
[4681 + (beg >> 14), 4681 + (end >> 14)],
|
|
25
|
-
]
|
|
26
|
+
] as const
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
export default class TabixIndex extends IndexFile {
|
|
29
30
|
async lineCount(refName: string, opts: Options = {}) {
|
|
30
31
|
const indexData = await this.parse(opts)
|
|
31
|
-
|
|
32
|
+
const refId = indexData.refNameToId[refName]
|
|
33
|
+
if (refId === undefined) {
|
|
32
34
|
return -1
|
|
33
35
|
}
|
|
34
|
-
const refId = indexData.refNameToId[refName]
|
|
35
36
|
const idx = indexData.indices[refId]
|
|
36
37
|
if (!idx) {
|
|
37
38
|
return -1
|
|
@@ -194,10 +195,10 @@ export default class TabixIndex extends IndexFile {
|
|
|
194
195
|
}
|
|
195
196
|
|
|
196
197
|
const indexData = await this.parse(opts)
|
|
197
|
-
|
|
198
|
+
const refId = indexData.refNameToId[refName]
|
|
199
|
+
if (refId === undefined) {
|
|
198
200
|
return []
|
|
199
201
|
}
|
|
200
|
-
const refId = indexData.refNameToId[refName]
|
|
201
202
|
const ba = indexData.indices[refId]
|
|
202
203
|
if (!ba) {
|
|
203
204
|
return []
|
package/src/util.ts
CHANGED
|
@@ -15,14 +15,15 @@ class AbortError extends Error {
|
|
|
15
15
|
public code: string | undefined
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Properly check if the given AbortSignal is aborted.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* with a `code` attribute set to `ERR_ABORTED`.
|
|
18
|
+
* Properly check if the given AbortSignal is aborted. Per the standard, if the
|
|
19
|
+
* signal reads as aborted, this function throws either a DOMException
|
|
20
|
+
* AbortError, or a regular error with a `code` attribute set to `ERR_ABORTED`.
|
|
22
21
|
*
|
|
23
22
|
* For convenience, passing `undefined` is a no-op
|
|
24
23
|
*
|
|
25
|
-
* @param {AbortSignal} [signal] an AbortSignal, or anything with an `aborted`
|
|
24
|
+
* @param {AbortSignal} [signal] an AbortSignal, or anything with an `aborted`
|
|
25
|
+
* attribute
|
|
26
|
+
*
|
|
26
27
|
* @returns nothing
|
|
27
28
|
*/
|
|
28
29
|
export function checkAbortSignal(signal?: AbortSignal) {
|
|
@@ -32,7 +33,6 @@ export function checkAbortSignal(signal?: AbortSignal) {
|
|
|
32
33
|
|
|
33
34
|
if (signal.aborted) {
|
|
34
35
|
if (typeof DOMException !== 'undefined') {
|
|
35
|
-
// eslint-disable-next-line no-undef
|
|
36
36
|
throw new DOMException('aborted', 'AbortError')
|
|
37
37
|
} else {
|
|
38
38
|
const e = new AbortError('aborted')
|
|
@@ -60,7 +60,7 @@ export function canMergeBlocks(chunk1: Chunk, chunk2: Chunk) {
|
|
|
60
60
|
)
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export function optimizeChunks(chunks: Chunk[], lowest
|
|
63
|
+
export function optimizeChunks(chunks: Chunk[], lowest?: VirtualOffset) {
|
|
64
64
|
const mergedChunks: Chunk[] = []
|
|
65
65
|
let lastChunk: Chunk | null = null
|
|
66
66
|
|
package/src/virtualOffset.ts
CHANGED
|
@@ -16,20 +16,6 @@ export default class VirtualOffset {
|
|
|
16
16
|
this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
|
|
17
17
|
)
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
static min(...args: VirtualOffset[]) {
|
|
21
|
-
let min
|
|
22
|
-
let i = 0
|
|
23
|
-
for (; !min; i += 1) {
|
|
24
|
-
min = args[i]
|
|
25
|
-
}
|
|
26
|
-
for (; i < args.length; i += 1) {
|
|
27
|
-
if (min.compareTo(args[i]) > 0) {
|
|
28
|
-
min = args[i]
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return min
|
|
32
|
-
}
|
|
33
19
|
}
|
|
34
20
|
export function fromBytes(bytes: Buffer, offset = 0, bigendian = false) {
|
|
35
21
|
if (bigendian) {
|
|
@@ -37,12 +23,12 @@ export function fromBytes(bytes: Buffer, offset = 0, bigendian = false) {
|
|
|
37
23
|
}
|
|
38
24
|
|
|
39
25
|
return new VirtualOffset(
|
|
40
|
-
bytes[offset + 7] * 0x10000000000 +
|
|
41
|
-
bytes[offset + 6] * 0x100000000 +
|
|
42
|
-
bytes[offset + 5] * 0x1000000 +
|
|
43
|
-
bytes[offset + 4] * 0x10000 +
|
|
44
|
-
bytes[offset + 3] * 0x100 +
|
|
45
|
-
bytes[offset + 2]
|
|
46
|
-
(bytes[offset + 1] << 8) | bytes[offset]
|
|
26
|
+
bytes[offset + 7]! * 0x10000000000 +
|
|
27
|
+
bytes[offset + 6]! * 0x100000000 +
|
|
28
|
+
bytes[offset + 5]! * 0x1000000 +
|
|
29
|
+
bytes[offset + 4]! * 0x10000 +
|
|
30
|
+
bytes[offset + 3]! * 0x100 +
|
|
31
|
+
bytes[offset + 2]!,
|
|
32
|
+
(bytes[offset + 1]! << 8) | bytes[offset]!,
|
|
47
33
|
)
|
|
48
34
|
}
|