@gmod/bam 7.3.2 → 7.3.4

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/esm/util.js CHANGED
@@ -47,7 +47,7 @@ export function optimizeChunks(chunks, lowest) {
47
47
  const cmp = chunkMaxBlock - lastMaxBlock ||
48
48
  chunk.maxv.dataPosition - lastChunk.maxv.dataPosition;
49
49
  if (cmp > 0) {
50
- mergedChunks[mergedChunks.length - 1] = new Chunk(lastChunk.minv, chunk.maxv, lastChunk.bin);
50
+ mergedChunks[mergedChunks.length - 1] = new Chunk(lastChunk.minv, chunk.maxv, lastChunk.bin, chunk.endPosition);
51
51
  lastMaxBlock = chunkMaxBlock;
52
52
  }
53
53
  }
@@ -64,6 +64,38 @@ export function parsePseudoBin(bytes, offset) {
64
64
  lineCount: longFromBytesToUnsigned(bytes, offset),
65
65
  };
66
66
  }
67
+ // Tighten each chunk's endPosition (default: a full max-size BGZF block past
68
+ // maxv) down to the next known block boundary. Every chunk min/maxv blockPosition
69
+ // and every extraBoundary (e.g. linear-index entries) is a real BGZF block start;
70
+ // since blocks don't overlap, the first boundary strictly greater than a chunk's
71
+ // maxv.blockPosition is an upper bound on where that final block ends — always at
72
+ // least the true block end, so the clamped fetch still contains the whole block.
73
+ // Shrinks both the byte estimate and the actual fetch with no extra I/O.
74
+ export function clampChunkEnds(chunks, extraBoundaries = []) {
75
+ const boundaries = [...extraBoundaries];
76
+ for (const c of chunks) {
77
+ boundaries.push(c.minv.blockPosition, c.maxv.blockPosition);
78
+ }
79
+ boundaries.sort((a, b) => a - b);
80
+ for (const c of chunks) {
81
+ const max = c.maxv.blockPosition;
82
+ // first boundary strictly greater than max
83
+ let lo = 0;
84
+ let hi = boundaries.length;
85
+ while (lo < hi) {
86
+ const mid = (lo + hi) >>> 1;
87
+ if (boundaries[mid] > max) {
88
+ hi = mid;
89
+ }
90
+ else {
91
+ lo = mid + 1;
92
+ }
93
+ }
94
+ if (lo < boundaries.length) {
95
+ c.endPosition = Math.min(c.endPosition, boundaries[lo]);
96
+ }
97
+ }
98
+ }
67
99
  // Parse the BAM reference-sequence table (SAMv1.pdf §4.2). Returns undefined
68
100
  // if `uncba` doesn't yet contain the full table — caller fetches more bytes
69
101
  // and retries.
package/esm/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
@@ -11,4 +11,4 @@ export declare class VirtualOffset {
11
11
  toString(): string;
12
12
  compareTo(b: VirtualOffset): number;
13
13
  }
14
- export declare function fromBytes(bytes: Uint8Array, offset?: number, bigendian?: boolean): VirtualOffset;
14
+ export declare function fromBytes(bytes: Uint8Array, offset?: number): VirtualOffset;
@@ -12,10 +12,7 @@ export class VirtualOffset {
12
12
  return (this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition);
13
13
  }
14
14
  }
15
- export function fromBytes(bytes, offset = 0, bigendian = false) {
16
- if (bigendian) {
17
- throw new Error('big-endian virtual file offsets not implemented');
18
- }
15
+ export function fromBytes(bytes, offset = 0) {
19
16
  return new VirtualOffset(bytes[offset + 7] * 0x10000000000 +
20
17
  bytes[offset + 6] * 0x100000000 +
21
18
  bytes[offset + 5] * 0x1000000 +
@@ -1 +1 @@
1
- {"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,aAAa;IACjB,aAAa,CAAQ;IACrB,YAAY,CAAQ;IAC3B,YAAY,aAAqB,EAAE,YAAoB;QACrD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA,CAAC,wCAAwC;QAC3E,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA,CAAC,sCAAsC;IACzE,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,EAAE,CAAA;IACrD,CAAC;IAED,SAAS,CAAC,CAAgB;QACxB,OAAO,CACL,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAC3E,CAAA;IACH,CAAC;CACF;AACD,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,MAAM,GAAG,CAAC,EAAE,SAAS,GAAG,KAAK;IACxE,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACpE,CAAC;IAED,OAAO,IAAI,aAAa,CACtB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,aAAa;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,WAAW;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,SAAS;QAC9B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,OAAO;QAC5B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,KAAK;QAC1B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EACpB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAC3C,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,aAAa;IACjB,aAAa,CAAQ;IACrB,YAAY,CAAQ;IAC3B,YAAY,aAAqB,EAAE,YAAoB;QACrD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA,CAAC,wCAAwC;QAC3E,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA,CAAC,sCAAsC;IACzE,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,EAAE,CAAA;IACrD,CAAC;IAED,SAAS,CAAC,CAAgB;QACxB,OAAO,CACL,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAC3E,CAAA;IACH,CAAC;CACF;AACD,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,MAAM,GAAG,CAAC;IACrD,OAAO,IAAI,aAAa,CACtB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,aAAa;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,WAAW;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,SAAS;QAC9B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,OAAO;QAC5B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,KAAK;QAC1B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EACpB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAC3C,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gmod/bam",
3
- "version": "7.3.2",
3
+ "version": "7.3.4",
4
4
  "description": "Parser for BAM and BAM index (bai) files",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/bai.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import Chunk from './chunk.ts'
2
2
  import IndexFile, { memoizeByRefId } from './indexFile.ts'
3
- import { findFirstData, parsePseudoBin } from './util.ts'
3
+ import { clampChunkEnds, findFirstData, parsePseudoBin } from './util.ts'
4
4
  import { fromBytes } from './virtualOffset.ts'
5
5
 
6
6
  import type { ParsedIndexBase, RefIndex } from './indexFile.ts'
@@ -146,6 +146,10 @@ export default class BAI extends IndexFile<BaiParsed> {
146
146
  curr += 8
147
147
  }
148
148
 
149
+ clampChunkEnds(
150
+ Object.values(binIndex).flat(),
151
+ linearIndex.map(v => v.blockPosition),
152
+ )
149
153
  return {
150
154
  binIndex,
151
155
  linearIndex,
package/src/chunk.ts CHANGED
@@ -2,12 +2,26 @@ import type { Offset } from './virtualOffset.ts'
2
2
 
3
3
  // little class representing a chunk in the index
4
4
  export default class Chunk {
5
+ public minv: Offset
6
+ public maxv: Offset
7
+ public bin: number
8
+ // Absolute byte offset where the fetch for this chunk ends. The compressed
9
+ // size of the final BGZF block (the one at maxv.blockPosition) is unknown
10
+ // from the index, so this defaults to a full max-size block past maxv. It can
11
+ // be tightened to the next known block boundary via clampChunkEnds.
12
+ public endPosition: number
13
+
5
14
  constructor(
6
- public minv: Offset,
7
- public maxv: Offset,
8
- public bin: number,
9
- public _fetchedSize?: number,
10
- ) {}
15
+ minv: Offset,
16
+ maxv: Offset,
17
+ bin: number,
18
+ endPosition = maxv.blockPosition + (1 << 16),
19
+ ) {
20
+ this.minv = minv
21
+ this.maxv = maxv
22
+ this.bin = bin
23
+ this.endPosition = endPosition
24
+ }
11
25
 
12
26
  toString() {
13
27
  return `${this.minv.toString()}..${this.maxv.toString()} (bin ${
@@ -24,9 +38,6 @@ export default class Chunk {
24
38
  }
25
39
 
26
40
  fetchedSize() {
27
- if (this._fetchedSize !== undefined) {
28
- return this._fetchedSize
29
- }
30
- return this.maxv.blockPosition + (1 << 16) - this.minv.blockPosition
41
+ return this.endPosition - this.minv.blockPosition
31
42
  }
32
43
  }
package/src/csi.ts CHANGED
@@ -2,7 +2,12 @@ import { unzip } from '@gmod/bgzf-filehandle'
2
2
 
3
3
  import Chunk from './chunk.ts'
4
4
  import IndexFile, { memoizeByRefId } from './indexFile.ts'
5
- import { findFirstData, parseNameBytes, parsePseudoBin } from './util.ts'
5
+ import {
6
+ clampChunkEnds,
7
+ findFirstData,
8
+ parseNameBytes,
9
+ parsePseudoBin,
10
+ } from './util.ts'
6
11
  import { VirtualOffset, fromBytes } from './virtualOffset.ts'
7
12
 
8
13
  import type { BaseOpts } from './util.ts'
@@ -150,6 +155,7 @@ export default class CSI extends IndexFile {
150
155
  }
151
156
  }
152
157
 
158
+ clampChunkEnds(Object.values(binIndex).flat())
153
159
  return {
154
160
  binIndex,
155
161
  stats: pseudoBinStats,
package/src/long.ts CHANGED
@@ -1,5 +1,4 @@
1
- export const TWO_PWR_16_DBL = 1 << 16
2
- export const TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL
1
+ const TWO_PWR_32_DBL = 2 ** 32
3
2
 
4
3
  // avoids dependency on long.js
5
4
  export function longFromBytesToUnsigned(source: Uint8Array, i = 0) {
package/src/record.ts CHANGED
@@ -127,6 +127,97 @@ function bArrayByteLength(Btype: number, limit: number) {
127
127
  }
128
128
  }
129
129
 
130
+ // Cursor position just past a tag's value — i.e. the start of the next tag —
131
+ // given the value starts at `p`. For null-terminated Z/H this steps over the
132
+ // terminator. Returns 0 for an unknown type, whose value width is unknowable so
133
+ // the caller must stop. Shared by _findTag and _computeTags so the two loops
134
+ // can't drift in how they walk the tag layout. (0 is an impossible real end:
135
+ // `p` is always past the fixed record prefix.)
136
+ function tagValueEnd(
137
+ ba: Uint8Array,
138
+ dataView: DataView,
139
+ type: number,
140
+ p: number,
141
+ blockEnd: number,
142
+ ) {
143
+ switch (type) {
144
+ case 0x41: // 'A'
145
+ case 0x63: // 'c'
146
+ case 0x43: // 'C'
147
+ return p + 1
148
+ case 0x73: // 's'
149
+ case 0x53: // 'S'
150
+ return p + 2
151
+ case 0x69: // 'i'
152
+ case 0x49: // 'I'
153
+ case 0x66: {
154
+ // 'f'
155
+ return p + 4
156
+ }
157
+ case 0x5a: // 'Z'
158
+ case 0x48: {
159
+ // 'H'
160
+ let q = p
161
+ while (q < blockEnd && ba[q] !== 0) {
162
+ q++
163
+ }
164
+ return q + 1 // step past the null terminator
165
+ }
166
+ case 0x42: {
167
+ // 'B'
168
+ const Btype = ba[p]!
169
+ const limit = dataView.getInt32(p + 1, true)
170
+ return p + 5 + bArrayByteLength(Btype, limit)
171
+ }
172
+ default:
173
+ console.error('Unknown BAM tag type', type)
174
+ return 0
175
+ }
176
+ }
177
+
178
+ // Decode the value of a tag of `type` whose bytes start at `p`; `end` is the
179
+ // next-tag cursor from tagValueEnd (used only to bound Z/H strings, whose bytes
180
+ // run up to the null terminator at end-1). When `raw`, Z/H return the undecoded
181
+ // byte subarray. Assumes `type` is a known scalar/string/B type.
182
+ function decodeTagValue(
183
+ ba: Uint8Array,
184
+ dataView: DataView,
185
+ type: number,
186
+ p: number,
187
+ end: number,
188
+ raw: boolean,
189
+ ): unknown {
190
+ switch (type) {
191
+ case 0x41: // 'A'
192
+ return String.fromCharCode(ba[p]!)
193
+ case 0x69: // 'i'
194
+ return dataView.getInt32(p, true)
195
+ case 0x49: // 'I'
196
+ return dataView.getUint32(p, true)
197
+ case 0x63: // 'c'
198
+ return dataView.getInt8(p)
199
+ case 0x43: // 'C'
200
+ return dataView.getUint8(p)
201
+ case 0x73: // 's'
202
+ return dataView.getInt16(p, true)
203
+ case 0x53: // 'S'
204
+ return dataView.getUint16(p, true)
205
+ case 0x66: // 'f'
206
+ return dataView.getFloat32(p, true)
207
+ case 0x5a: // 'Z'
208
+ case 0x48: // 'H'
209
+ return raw
210
+ ? ba.subarray(p, end - 1)
211
+ : textDecoder.decode(ba.subarray(p, end - 1))
212
+ default: {
213
+ // 'B'
214
+ const Btype = ba[p]!
215
+ const limit = dataView.getInt32(p + 1, true)
216
+ return decodeBArrayTag(ba, dataView, p + 5, Btype, limit)
217
+ }
218
+ }
219
+ }
220
+
130
221
  export default class BamRecord {
131
222
  public fileOffset: number
132
223
  private _byteArray: Uint8Array
@@ -261,172 +352,47 @@ export default class BamRecord {
261
352
  private _findTag(tagName: string, raw: boolean) {
262
353
  const tag1 = tagName.charCodeAt(0)
263
354
  const tag2 = tagName.charCodeAt(1)
264
-
265
- let p = this.tagsStart
266
-
267
355
  const blockEnd = this._end
268
356
  const ba = this._byteArray
357
+ let p = this.tagsStart
269
358
  while (p < blockEnd) {
270
- const currentTag1 = ba[p]
271
- const currentTag2 = ba[p + 1]
272
- const type = ba[p + 2]
273
- p += 3
274
-
275
- const isMatch = currentTag1 === tag1 && currentTag2 === tag2
276
-
277
- switch (type) {
278
- case 0x41: // 'A'
279
- if (isMatch) {
280
- return String.fromCharCode(ba[p]!)
281
- }
282
- p += 1
283
- break
284
- case 0x69: // 'i'
285
- if (isMatch) {
286
- return this._dataView.getInt32(p, true)
287
- }
288
- p += 4
289
- break
290
- case 0x49: // 'I'
291
- if (isMatch) {
292
- return this._dataView.getUint32(p, true)
293
- }
294
- p += 4
295
- break
296
- case 0x63: // 'c'
297
- if (isMatch) {
298
- return this._dataView.getInt8(p)
299
- }
300
- p += 1
301
- break
302
- case 0x43: // 'C'
303
- if (isMatch) {
304
- return this._dataView.getUint8(p)
305
- }
306
- p += 1
307
- break
308
- case 0x73: // 's'
309
- if (isMatch) {
310
- return this._dataView.getInt16(p, true)
311
- }
312
- p += 2
313
- break
314
- case 0x53: // 'S'
315
- if (isMatch) {
316
- return this._dataView.getUint16(p, true)
317
- }
318
- p += 2
319
- break
320
- case 0x66: // 'f'
321
- if (isMatch) {
322
- return this._dataView.getFloat32(p, true)
323
- }
324
- p += 4
325
- break
326
- case 0x5a: // 'Z'
327
- case 0x48: {
328
- // 'H'
329
- const start = p
330
- while (p < blockEnd && ba[p] !== 0) {
331
- p++
332
- }
333
- if (isMatch) {
334
- return raw
335
- ? ba.subarray(start, p)
336
- : textDecoder.decode(ba.subarray(start, p))
337
- }
338
- p++ // advance past null terminator
339
- break
340
- }
341
- case 0x42: {
342
- // 'B'
343
- const Btype = ba[p++]!
344
- const limit = this._dataView.getInt32(p, true)
345
- p += 4
346
- if (isMatch) {
347
- return decodeBArrayTag(ba, this._dataView, p, Btype, limit)
348
- }
349
- p += bArrayByteLength(Btype, limit)
350
- break
351
- }
352
- default:
353
- if (type !== undefined) {
354
- console.error('Unknown BAM tag type', type)
355
- }
356
- break
359
+ const isMatch = ba[p] === tag1 && ba[p + 1] === tag2
360
+ const type = ba[p + 2]!
361
+ const valueStart = p + 3
362
+ const end = tagValueEnd(ba, this._dataView, type, valueStart, blockEnd)
363
+ if (end === 0) {
364
+ break // unknown type: can't compute how far to advance
365
+ }
366
+ if (isMatch) {
367
+ return decodeTagValue(ba, this._dataView, type, valueStart, end, raw)
357
368
  }
369
+ p = end
358
370
  }
359
371
  return undefined
360
372
  }
361
373
 
362
374
  private _computeTags() {
363
- let p = this.tagsStart
364
-
365
375
  const blockEnd = this._end
366
376
  const ba = this._byteArray
367
377
  const tags: Record<string, unknown> = {}
378
+ let p = this.tagsStart
368
379
  while (p < blockEnd) {
369
380
  const tag = String.fromCharCode(ba[p]!, ba[p + 1]!)
370
381
  const type = ba[p + 2]!
371
- p += 3
372
-
373
- switch (type) {
374
- case 0x41: // 'A'
375
- tags[tag] = String.fromCharCode(ba[p]!)
376
- p += 1
377
- break
378
- case 0x69: // 'i'
379
- tags[tag] = this._dataView.getInt32(p, true)
380
- p += 4
381
- break
382
- case 0x49: // 'I'
383
- tags[tag] = this._dataView.getUint32(p, true)
384
- p += 4
385
- break
386
- case 0x63: // 'c'
387
- tags[tag] = this._dataView.getInt8(p)
388
- p += 1
389
- break
390
- case 0x43: // 'C'
391
- tags[tag] = this._dataView.getUint8(p)
392
- p += 1
393
- break
394
- case 0x73: // 's'
395
- tags[tag] = this._dataView.getInt16(p, true)
396
- p += 2
397
- break
398
- case 0x53: // 'S'
399
- tags[tag] = this._dataView.getUint16(p, true)
400
- p += 2
401
- break
402
- case 0x66: // 'f'
403
- tags[tag] = this._dataView.getFloat32(p, true)
404
- p += 4
405
- break
406
- case 0x5a: // 'Z'
407
- case 0x48: {
408
- // 'H'
409
- const start = p
410
- while (p < blockEnd && ba[p] !== 0) {
411
- p++
412
- }
413
- tags[tag] = textDecoder.decode(ba.subarray(start, p))
414
- p++ // advance past null terminator
415
- break
416
- }
417
- case 0x42: {
418
- // 'B'
419
- const Btype = ba[p++]!
420
- const limit = this._dataView.getInt32(p, true)
421
- p += 4
422
- tags[tag] = decodeBArrayTag(ba, this._dataView, p, Btype, limit)
423
- p += bArrayByteLength(Btype, limit)
424
- break
425
- }
426
- default:
427
- console.error('Unknown BAM tag type', type)
428
- break
382
+ const valueStart = p + 3
383
+ const end = tagValueEnd(ba, this._dataView, type, valueStart, blockEnd)
384
+ if (end === 0) {
385
+ break // unknown type: can't compute how far to advance
429
386
  }
387
+ tags[tag] = decodeTagValue(
388
+ ba,
389
+ this._dataView,
390
+ type,
391
+ valueStart,
392
+ end,
393
+ false,
394
+ )
395
+ p = end
430
396
  }
431
397
  return tags
432
398
  }
package/src/util.ts CHANGED
@@ -99,6 +99,7 @@ export function optimizeChunks(chunks: Chunk[], lowest?: Offset) {
99
99
  lastChunk.minv,
100
100
  chunk.maxv,
101
101
  lastChunk.bin,
102
+ chunk.endPosition,
102
103
  )
103
104
  lastMaxBlock = chunkMaxBlock
104
105
  }
@@ -118,6 +119,39 @@ export function parsePseudoBin(bytes: Uint8Array, offset: number) {
118
119
  }
119
120
  }
120
121
 
122
+ // Tighten each chunk's endPosition (default: a full max-size BGZF block past
123
+ // maxv) down to the next known block boundary. Every chunk min/maxv blockPosition
124
+ // and every extraBoundary (e.g. linear-index entries) is a real BGZF block start;
125
+ // since blocks don't overlap, the first boundary strictly greater than a chunk's
126
+ // maxv.blockPosition is an upper bound on where that final block ends — always at
127
+ // least the true block end, so the clamped fetch still contains the whole block.
128
+ // Shrinks both the byte estimate and the actual fetch with no extra I/O.
129
+ export function clampChunkEnds(chunks: Chunk[], extraBoundaries: number[] = []) {
130
+ const boundaries = [...extraBoundaries]
131
+ for (const c of chunks) {
132
+ boundaries.push(c.minv.blockPosition, c.maxv.blockPosition)
133
+ }
134
+ boundaries.sort((a, b) => a - b)
135
+
136
+ for (const c of chunks) {
137
+ const max = c.maxv.blockPosition
138
+ // first boundary strictly greater than max
139
+ let lo = 0
140
+ let hi = boundaries.length
141
+ while (lo < hi) {
142
+ const mid = (lo + hi) >>> 1
143
+ if (boundaries[mid]! > max) {
144
+ hi = mid
145
+ } else {
146
+ lo = mid + 1
147
+ }
148
+ }
149
+ if (lo < boundaries.length) {
150
+ c.endPosition = Math.min(c.endPosition, boundaries[lo]!)
151
+ }
152
+ }
153
+ }
154
+
121
155
  // Parse the BAM reference-sequence table (SAMv1.pdf §4.2). Returns undefined
122
156
  // if `uncba` doesn't yet contain the full table — caller fetches more bytes
123
157
  // and retries.
@@ -23,11 +23,7 @@ export class VirtualOffset {
23
23
  )
24
24
  }
25
25
  }
26
- export function fromBytes(bytes: Uint8Array, offset = 0, bigendian = false) {
27
- if (bigendian) {
28
- throw new Error('big-endian virtual file offsets not implemented')
29
- }
30
-
26
+ export function fromBytes(bytes: Uint8Array, offset = 0) {
31
27
  return new VirtualOffset(
32
28
  bytes[offset + 7]! * 0x10000000000 +
33
29
  bytes[offset + 6]! * 0x100000000 +