@gmod/bbi 5.0.1 → 6.0.0

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/src/block-view.ts CHANGED
@@ -1,7 +1,6 @@
1
- import { Buffer } from 'buffer'
2
1
  import { Observer } from 'rxjs'
3
2
  import AbortablePromiseCache from '@gmod/abortable-promise-cache'
4
- import { GenericFilehandle } from 'generic-filehandle'
3
+ import { GenericFilehandle } from 'generic-filehandle2'
5
4
  import QuickLRU from 'quick-lru'
6
5
 
7
6
  // locals
@@ -10,6 +9,9 @@ import { unzip } from './unzip'
10
9
  import { Feature } from './bbi'
11
10
  import { groupBlocks, checkAbortSignal } from './util'
12
11
 
12
+ const decoder =
13
+ typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined
14
+
13
15
  interface CoordRequest {
14
16
  chrId: number
15
17
  start: number
@@ -39,18 +41,15 @@ function coordFilter(s1: number, e1: number, s2: number, e2: number): boolean {
39
41
  */
40
42
 
41
43
  export class BlockView {
42
- private cirTreePromise?: Promise<{ bytesRead: number; buffer: Buffer }>
44
+ private cirTreePromise?: Promise<Uint8Array>
43
45
 
44
- private featureCache = new AbortablePromiseCache<ReadData, Buffer>({
46
+ private featureCache = new AbortablePromiseCache<ReadData, Uint8Array>({
45
47
  cache: new QuickLRU({ maxSize: 1000 }),
46
48
 
47
49
  fill: async (requestData, signal) => {
48
- const len = requestData.length
49
- const off = requestData.offset
50
- const { buffer } = await this.bbi.read(Buffer.alloc(len), 0, len, off, {
50
+ return this.bbi.read(requestData.length, requestData.offset, {
51
51
  signal,
52
52
  })
53
- return buffer
54
53
  },
55
54
  })
56
55
 
@@ -58,7 +57,6 @@ export class BlockView {
58
57
  private bbi: GenericFilehandle,
59
58
  private refsByName: any,
60
59
  private cirTreeOffset: number,
61
- private isBigEndian: boolean,
62
60
  private isCompressed: boolean,
63
61
  private blockType: string,
64
62
  ) {
@@ -75,31 +73,23 @@ export class BlockView {
75
73
  opts?: Options,
76
74
  ) {
77
75
  try {
78
- const { refsByName, bbi, cirTreeOffset, isBigEndian } = this
76
+ const { refsByName, bbi, cirTreeOffset } = this
79
77
  const chrId = refsByName[chrName]
80
78
  if (chrId === undefined) {
81
79
  observer.complete()
82
80
  }
83
81
  const request = { chrId, start, end }
84
82
  if (!this.cirTreePromise) {
85
- this.cirTreePromise = bbi.read(
86
- Buffer.alloc(48),
87
- 0,
88
- 48,
89
- cirTreeOffset,
90
- opts,
91
- )
83
+ this.cirTreePromise = bbi.read(48, cirTreeOffset, opts)
92
84
  }
93
- const { buffer } = await this.cirTreePromise
94
- const cirBlockSize = isBigEndian
95
- ? buffer.readUInt32BE(4)
96
- : buffer.readUInt32LE(4)
85
+ const buffer = await this.cirTreePromise
86
+ const dataView = new DataView(buffer.buffer)
87
+ const cirBlockSize = dataView.getUint32(4, true)
97
88
  let blocksToFetch: any[] = []
98
89
  let outstanding = 0
99
- const le = true
100
90
 
101
91
  const cirFobRecur2 = (
102
- cirBlockData: Buffer,
92
+ cirBlockData: Uint8Array,
103
93
  offset2: number,
104
94
  level: number,
105
95
  ) => {
@@ -112,22 +102,22 @@ export class BlockView {
112
102
 
113
103
  const isLeaf = dataView.getUint8(offset)
114
104
  offset += 2 // 1 skip
115
- const cnt = dataView.getUint16(offset, le)
105
+ const cnt = dataView.getUint16(offset, true)
116
106
  offset += 2
117
107
  if (isLeaf === 1) {
118
108
  const blocksToFetch2 = []
119
109
  for (let i = 0; i < cnt; i++) {
120
- const startChrom = dataView.getUint32(offset, le)
110
+ const startChrom = dataView.getUint32(offset, true)
121
111
  offset += 4
122
- const startBase = dataView.getUint32(offset, le)
112
+ const startBase = dataView.getUint32(offset, true)
123
113
  offset += 4
124
- const endChrom = dataView.getUint32(offset, le)
114
+ const endChrom = dataView.getUint32(offset, true)
125
115
  offset += 4
126
- const endBase = dataView.getUint32(offset, le)
116
+ const endBase = dataView.getUint32(offset, true)
127
117
  offset += 4
128
- const blockOffset = Number(dataView.getBigUint64(offset, le))
118
+ const blockOffset = Number(dataView.getBigUint64(offset, true))
129
119
  offset += 8
130
- const blockSize = Number(dataView.getBigUint64(offset, le))
120
+ const blockSize = Number(dataView.getBigUint64(offset, true))
131
121
  offset += 8
132
122
  blocksToFetch2.push({
133
123
  startChrom,
@@ -150,15 +140,15 @@ export class BlockView {
150
140
  } else if (isLeaf === 0) {
151
141
  const recurOffsets = []
152
142
  for (let i = 0; i < cnt; i++) {
153
- const startChrom = dataView.getUint32(offset, le)
143
+ const startChrom = dataView.getUint32(offset, true)
154
144
  offset += 4
155
- const startBase = dataView.getUint32(offset, le)
145
+ const startBase = dataView.getUint32(offset, true)
156
146
  offset += 4
157
- const endChrom = dataView.getUint32(offset, le)
147
+ const endChrom = dataView.getUint32(offset, true)
158
148
  offset += 4
159
- const endBase = dataView.getUint32(offset, le)
149
+ const endBase = dataView.getUint32(offset, true)
160
150
  offset += 4
161
- const blockOffset = Number(dataView.getBigUint64(offset, le))
151
+ const blockOffset = Number(dataView.getBigUint64(offset, true))
162
152
  offset += 8
163
153
  recurOffsets.push({
164
154
  startChrom,
@@ -202,7 +192,7 @@ export class BlockView {
202
192
  try {
203
193
  const length = fr.max - fr.min
204
194
  const offset = fr.min
205
- const resultBuffer: Buffer = await this.featureCache.get(
195
+ const resultBuffer = await this.featureCache.get(
206
196
  `${length}_${offset}`,
207
197
  { length, offset },
208
198
  opts?.signal,
@@ -215,7 +205,9 @@ export class BlockView {
215
205
  this.readFeatures(observer, blocksToFetch, {
216
206
  ...opts,
217
207
  request,
218
- }).catch(e => observer.error(e))
208
+ }).catch((e: unknown) => {
209
+ observer.error(e)
210
+ })
219
211
  }
220
212
  }
221
213
  }
@@ -251,14 +243,15 @@ export class BlockView {
251
243
  }
252
244
  }
253
245
 
254
- return cirFobRecur([Number(cirTreeOffset) + 48], 1)
246
+ cirFobRecur([Number(cirTreeOffset) + 48], 1)
247
+ return
255
248
  } catch (e) {
256
249
  observer.error(e)
257
250
  }
258
251
  }
259
252
 
260
253
  private parseSummaryBlock(
261
- b: Buffer,
254
+ b: Uint8Array,
262
255
  startOffset: number,
263
256
  request?: CoordRequest,
264
257
  ) {
@@ -308,23 +301,22 @@ export class BlockView {
308
301
  }
309
302
 
310
303
  private parseBigBedBlock(
311
- data: Buffer,
304
+ data: Uint8Array,
312
305
  startOffset: number,
313
306
  offset: number,
314
307
  request?: CoordRequest,
315
308
  ) {
316
309
  const items = [] as Feature[]
317
310
  let currOffset = startOffset
318
- const le = true
319
311
  const b = data
320
312
  const dataView = new DataView(b.buffer, b.byteOffset, b.length)
321
313
  while (currOffset < data.byteLength) {
322
314
  const c2 = currOffset
323
- const chromId = dataView.getUint32(currOffset, le)
315
+ const chromId = dataView.getUint32(currOffset, true)
324
316
  currOffset += 4
325
- const start = dataView.getInt32(currOffset, le)
317
+ const start = dataView.getInt32(currOffset, true)
326
318
  currOffset += 4
327
- const end = dataView.getInt32(currOffset, le)
319
+ const end = dataView.getInt32(currOffset, true)
328
320
  currOffset += 4
329
321
  let i = currOffset
330
322
  for (; i < data.length; i++) {
@@ -332,7 +324,8 @@ export class BlockView {
332
324
  break
333
325
  }
334
326
  }
335
- const rest = data.subarray(currOffset, i).toString()
327
+ const b = data.subarray(currOffset, i)
328
+ const rest = decoder?.decode(b) ?? b.toString()
336
329
  currOffset = i + 1
337
330
  items.push({
338
331
  chromId,
@@ -351,7 +344,7 @@ export class BlockView {
351
344
  }
352
345
 
353
346
  private parseBigWigBlock(
354
- buffer: Buffer,
347
+ buffer: Uint8Array,
355
348
  startOffset: number,
356
349
  req?: CoordRequest,
357
350
  ) {
@@ -443,32 +436,28 @@ export class BlockView {
443
436
  )
444
437
  for (const block of blockGroup.blocks) {
445
438
  checkAbortSignal(signal)
446
- let blockOffset = Number(block.offset) - Number(blockGroup.offset)
447
- let resultData = data
439
+ let resultData = data.subarray(
440
+ Number(block.offset) - Number(blockGroup.offset),
441
+ )
448
442
  if (isCompressed) {
449
- resultData = unzip(data.subarray(blockOffset))
450
- blockOffset = 0
443
+ resultData = unzip(resultData)
451
444
  }
452
445
  checkAbortSignal(signal)
453
446
 
454
447
  switch (blockType) {
455
448
  case 'summary': {
456
- observer.next(
457
- this.parseSummaryBlock(resultData, blockOffset, request),
458
- )
449
+ observer.next(this.parseSummaryBlock(resultData, 0, request))
459
450
  break
460
451
  }
461
452
  case 'bigwig': {
462
- observer.next(
463
- this.parseBigWigBlock(resultData, blockOffset, request),
464
- )
453
+ observer.next(this.parseBigWigBlock(resultData, 0, request))
465
454
  break
466
455
  }
467
456
  case 'bigbed': {
468
457
  observer.next(
469
458
  this.parseBigBedBlock(
470
459
  resultData,
471
- blockOffset,
460
+ 0,
472
461
  Number(block.offset) * (1 << 8),
473
462
  request,
474
463
  ),
package/src/unzip-pako.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { Buffer } from 'buffer'
2
1
  import { inflateRaw } from 'pako'
3
2
 
4
- export function unzip(input: Buffer) {
3
+ export function unzip(input: Uint8Array) {
5
4
  return inflateRaw(input.subarray(2))
6
5
  }