@gmod/tabix 1.5.14 → 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.
Files changed (48) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +9 -0
  3. package/dist/chunk.js +0 -1
  4. package/dist/chunk.js.map +1 -1
  5. package/dist/csi.d.ts +1 -1
  6. package/dist/csi.js +4 -4
  7. package/dist/csi.js.map +1 -1
  8. package/dist/indexFile.js +1 -1
  9. package/dist/indexFile.js.map +1 -1
  10. package/dist/tabix-bundle.js +2 -0
  11. package/dist/tabix-bundle.js.LICENSE.txt +8 -0
  12. package/dist/tabixIndexedFile.d.ts +43 -20
  13. package/dist/tabixIndexedFile.js +66 -42
  14. package/dist/tabixIndexedFile.js.map +1 -1
  15. package/dist/tbi.js +6 -5
  16. package/dist/tbi.js.map +1 -1
  17. package/dist/util.d.ts +7 -6
  18. package/dist/util.js +6 -5
  19. package/dist/util.js.map +1 -1
  20. package/dist/virtualOffset.d.ts +0 -1
  21. package/dist/virtualOffset.js +0 -13
  22. package/dist/virtualOffset.js.map +1 -1
  23. package/esm/chunk.js +0 -1
  24. package/esm/chunk.js.map +1 -1
  25. package/esm/csi.d.ts +1 -1
  26. package/esm/csi.js +4 -4
  27. package/esm/csi.js.map +1 -1
  28. package/esm/indexFile.js +1 -1
  29. package/esm/indexFile.js.map +1 -1
  30. package/esm/tabixIndexedFile.d.ts +43 -20
  31. package/esm/tabixIndexedFile.js +67 -43
  32. package/esm/tabixIndexedFile.js.map +1 -1
  33. package/esm/tbi.js +6 -5
  34. package/esm/tbi.js.map +1 -1
  35. package/esm/util.d.ts +7 -6
  36. package/esm/util.js +6 -5
  37. package/esm/util.js.map +1 -1
  38. package/esm/virtualOffset.d.ts +0 -1
  39. package/esm/virtualOffset.js +0 -13
  40. package/esm/virtualOffset.js.map +1 -1
  41. package/package.json +20 -17
  42. package/src/chunk.ts +1 -1
  43. package/src/csi.ts +6 -5
  44. package/src/indexFile.ts +1 -1
  45. package/src/tabixIndexedFile.ts +73 -51
  46. package/src/tbi.ts +7 -6
  47. package/src/util.ts +7 -6
  48. package/src/virtualOffset.ts +7 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmod/tabix",
3
- "version": "1.5.14",
3
+ "version": "1.5.15",
4
4
  "description": "Read Tabix-indexed files, supports both .tbi and .csi indexes",
5
5
  "license": "MIT",
6
6
  "repository": "GMOD/tabix-js",
@@ -20,16 +20,17 @@
20
20
  "src"
21
21
  ],
22
22
  "scripts": {
23
- "test": "jest",
24
- "coverage": "npm test -- --coverage",
25
- "lint": "eslint --report-unused-disable-directives --max-warnings 0 src test",
23
+ "test": "vitest",
24
+ "lint": "eslint --report-unused-disable-directives --max-warnings 0",
25
+ "format": "prettier --write .",
26
26
  "clean": "rimraf dist esm",
27
27
  "prebuild": "npm run clean && npm run lint",
28
28
  "build:esm": "tsc --target es2018 --outDir esm",
29
29
  "build:es5": "tsc --target es2015 --module commonjs --outDir dist",
30
30
  "build": "npm run build:esm && npm run build:es5",
31
- "preversion": "npm run lint && npm test && npm run build",
32
- "prepublishOnly": "npm run lint && npm test && npm run build",
31
+ "postbuild": "webpack",
32
+ "preversion": "npm run lint && npm test run && npm run build",
33
+ "prepublishOnly": "npm run lint && npm test run && npm run build",
33
34
  "version": "standard-changelog && git add CHANGELOG.md",
34
35
  "postversion": "git push --follow-tags"
35
36
  },
@@ -47,23 +48,25 @@
47
48
  },
48
49
  "devDependencies": {
49
50
  "@eslint/eslintrc": "^3.1.0",
50
- "@eslint/js": "^9.7.0",
51
- "@types/jest": "^29.5.12",
51
+ "@eslint/js": "^9.9.0",
52
52
  "@types/long": "^4.0.0",
53
53
  "@types/node": "^20.11.16",
54
- "@typescript-eslint/eslint-plugin": "^7.17.0",
55
- "@typescript-eslint/parser": "^7.17.0",
56
- "eslint": "^9.0.0",
54
+ "@typescript-eslint/eslint-plugin": "^8.0.1",
55
+ "@typescript-eslint/parser": "^8.0.1",
56
+ "@vitest/coverage-v8": "^2.0.5",
57
+ "buffer": "^6.0.3",
58
+ "eslint": "^9.9.0",
57
59
  "eslint-config-prettier": "^9.1.0",
58
60
  "eslint-plugin-prettier": "^5.0.1",
59
- "eslint-plugin-unicorn": "^54.0.0",
60
- "jest": "^29.7.0",
61
- "jest-environment-jsdom": "^29.5.0",
62
- "prettier": "^3.2.5",
61
+ "eslint-plugin-unicorn": "^55.0.0",
62
+ "prettier": "^3.3.3",
63
63
  "rimraf": "^6.0.1",
64
64
  "standard-changelog": "^6.0.0",
65
- "ts-jest": "^29.1.1",
66
- "typescript": "^5.3.3"
65
+ "typescript": "^5.3.3",
66
+ "typescript-eslint": "^8.0.1",
67
+ "vitest": "^2.0.5",
68
+ "webpack": "^5.93.0",
69
+ "webpack-cli": "^5.1.4"
67
70
  },
68
71
  "publishConfig": {
69
72
  "access": "public"
package/src/chunk.ts CHANGED
@@ -20,7 +20,7 @@ export default class Chunk {
20
20
  }
21
21
 
22
22
  toUniqueString() {
23
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
23
+
24
24
  return `${this.minv}..${this.maxv} (bin ${
25
25
  this.bin
26
26
  }, fetchedSize ${this.fetchedSize()})`
package/src/csi.ts CHANGED
@@ -30,10 +30,10 @@ export default class CSI extends IndexFile {
30
30
  }
31
31
  async lineCount(refName: string, opts: Options = {}): Promise<number> {
32
32
  const indexData = await this.parse(opts)
33
- if (!indexData) {
33
+ const refId = indexData.refNameToId[refName]
34
+ if (refId === undefined) {
34
35
  return -1
35
36
  }
36
- const refId = indexData.refNameToId[refName]
37
37
  const idx = indexData.indices[refId]
38
38
  if (!idx) {
39
39
  return -1
@@ -44,6 +44,7 @@ export default class CSI extends IndexFile {
44
44
  }
45
45
  return -1
46
46
  }
47
+
47
48
  indexCov() {
48
49
  throw new Error('CSI indexes do not support indexcov')
49
50
  }
@@ -206,10 +207,10 @@ export default class CSI extends IndexFile {
206
207
  }
207
208
 
208
209
  const indexData = await this.parse(opts)
209
- if (!indexData) {
210
+ const refId = indexData.refNameToId[refName]
211
+ if (refId === undefined) {
210
212
  return []
211
213
  }
212
- const refId = indexData.refNameToId[refName]
213
214
  const ba = indexData.indices[refId]
214
215
  if (!ba) {
215
216
  return []
@@ -258,7 +259,7 @@ export default class CSI extends IndexFile {
258
259
  `query ${beg}-${end} is too large for current binning scheme (shift ${this.minShift}, depth ${this.depth}), try a smaller query or a coarser index binning scheme`,
259
260
  )
260
261
  }
261
- bins.push([b, e])
262
+ bins.push([b, e] as const)
262
263
  }
263
264
  return bins
264
265
  }
package/src/indexFile.ts CHANGED
@@ -65,7 +65,7 @@ export default abstract class IndexFile {
65
65
 
66
66
  async parse(opts: Options = {}) {
67
67
  if (!this.parseP) {
68
- this.parseP = this._parse(opts).catch(e => {
68
+ this.parseP = this._parse(opts).catch((e: unknown) => {
69
69
  this.parseP = undefined
70
70
  throw e
71
71
  })
@@ -1,7 +1,7 @@
1
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
- * @param {number} [args.yieldTime] yield to main thread after N milliseconds if reading features is taking a long time to avoid hanging main thread
50
- * @param {function} [args.renameRefSeqs] optional function with sig `string => string` to transform
51
- * reference sequence names for the purpose of indexing and querying. note that the data that is returned is
52
- * not altered, just the names of the reference sequences that are used for querying.
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, or csiPath',
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
- * @param opts callback called for each line in the region. can also pass a object param containing obj.lineCallback, obj.signal, etc
131
- * @returns promise that is resolved when the whole read is finished, rejected on error
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
- if (opts === undefined) {
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
- * the file, which are the bytes up to the first
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
- * file, is the portion up to the first non-meta line
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
- * they occur in the file. reference sequence renaming is not applied
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
- * containing columnNumbers, metaChar, and format
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
- // basically, we want to avoid doing a split, because if the lines are really long
369
- // that could lead to us allocating a bunch of extra memory, which is slow
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 sequence
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
- // and stop when done
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) (zero-based half-open)
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
- if (!indexData) {
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
- if (!indexData) {
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
- * Per the standard, if the signal reads as aborted,
20
- * this function throws either a DOMException AbortError, or a regular error
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` attribute
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) {
@@ -59,7 +60,7 @@ export function canMergeBlocks(chunk1: Chunk, chunk2: Chunk) {
59
60
  )
60
61
  }
61
62
 
62
- export function optimizeChunks(chunks: Chunk[], lowest: VirtualOffset) {
63
+ export function optimizeChunks(chunks: Chunk[], lowest?: VirtualOffset) {
63
64
  const mergedChunks: Chunk[] = []
64
65
  let lastChunk: Chunk | null = null
65
66
 
@@ -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
  }