@gmod/bbi 4.0.6 → 5.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/CHANGELOG.md +6 -1
- package/dist/bbi.d.ts +20 -4
- package/dist/bbi.js +124 -104
- package/dist/bbi.js.map +1 -1
- package/dist/bigbed.js +88 -69
- package/dist/bigbed.js.map +1 -1
- package/dist/bigint-polyfill/polyfill.js +0 -10
- package/dist/bigint-polyfill/polyfill.js.map +1 -1
- package/dist/bigint-polyfill/pure.d.ts +0 -2
- package/dist/bigint-polyfill/pure.js +0 -26
- package/dist/bigint-polyfill/pure.js.map +1 -1
- package/dist/bigwig.js +3 -8
- package/dist/bigwig.js.map +1 -1
- package/dist/block-view.d.ts +4 -6
- package/dist/block-view.js +122 -131
- package/dist/block-view.js.map +1 -1
- package/dist/range.js +1 -1
- package/dist/range.js.map +1 -1
- package/dist/util.d.ts +12 -14
- package/dist/util.js +8 -14
- package/dist/util.js.map +1 -1
- package/esm/bbi.d.ts +20 -4
- package/esm/bbi.js +124 -104
- package/esm/bbi.js.map +1 -1
- package/esm/bigbed.js +88 -69
- package/esm/bigbed.js.map +1 -1
- package/esm/bigint-polyfill/polyfill.js +1 -11
- package/esm/bigint-polyfill/polyfill.js.map +1 -1
- package/esm/bigint-polyfill/pure.d.ts +0 -2
- package/esm/bigint-polyfill/pure.js +0 -24
- package/esm/bigint-polyfill/pure.js.map +1 -1
- package/esm/bigwig.js +3 -8
- package/esm/bigwig.js.map +1 -1
- package/esm/block-view.d.ts +4 -6
- package/esm/block-view.js +122 -131
- package/esm/block-view.js.map +1 -1
- package/esm/range.js +1 -1
- package/esm/range.js.map +1 -1
- package/esm/util.d.ts +12 -14
- package/esm/util.js +8 -14
- package/esm/util.js.map +1 -1
- package/package.json +4 -5
- package/src/bbi.ts +151 -115
- package/src/bigbed.ts +99 -80
- package/src/bigint-polyfill/polyfill.ts +1 -13
- package/src/bigint-polyfill/pure.ts +0 -36
- package/src/bigwig.ts +3 -9
- package/src/block-view.ts +133 -168
- package/src/range.ts +1 -1
- package/src/util.ts +16 -21
package/src/bigwig.ts
CHANGED
|
@@ -11,24 +11,18 @@ export class BigWig extends BBI {
|
|
|
11
11
|
* or scale used to infer the zoomLevel to use
|
|
12
12
|
*/
|
|
13
13
|
protected async getView(scale: number, opts: RequestOptions) {
|
|
14
|
-
const { zoomLevels, refsByName,
|
|
14
|
+
const { zoomLevels, refsByName, isBigEndian, uncompressBufSize } =
|
|
15
15
|
await this.getHeader(opts)
|
|
16
16
|
const basesPerPx = 1 / scale
|
|
17
|
-
|
|
18
|
-
if (!fileSize) {
|
|
19
|
-
// if we don't know the file size, we can't fetch the highest zoom level :-(
|
|
20
|
-
maxLevel -= 1
|
|
21
|
-
}
|
|
17
|
+
const maxLevel = zoomLevels.length - 1
|
|
22
18
|
|
|
23
19
|
for (let i = maxLevel; i >= 0; i -= 1) {
|
|
24
20
|
const zh = zoomLevels[i]
|
|
25
21
|
if (zh && zh.reductionLevel <= 2 * basesPerPx) {
|
|
26
|
-
const indexOffset = Number(zh.indexOffset)
|
|
27
|
-
|
|
28
22
|
return new BlockView(
|
|
29
23
|
this.bbi,
|
|
30
24
|
refsByName,
|
|
31
|
-
indexOffset,
|
|
25
|
+
zh.indexOffset,
|
|
32
26
|
isBigEndian,
|
|
33
27
|
uncompressBufSize > 0,
|
|
34
28
|
'summary',
|
package/src/block-view.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Buffer } from 'buffer'
|
|
2
2
|
import { Observer } from 'rxjs'
|
|
3
|
-
import { Parser } from 'binary-parser'
|
|
4
3
|
import AbortablePromiseCache from '@gmod/abortable-promise-cache'
|
|
5
4
|
import { GenericFilehandle } from 'generic-filehandle'
|
|
6
5
|
import QuickLRU from 'quick-lru'
|
|
@@ -16,23 +15,10 @@ interface CoordRequest {
|
|
|
16
15
|
start: number
|
|
17
16
|
end: number
|
|
18
17
|
}
|
|
19
|
-
interface DataBlock {
|
|
20
|
-
blockOffset: bigint
|
|
21
|
-
blockSize: bigint
|
|
22
|
-
startChrom: number
|
|
23
|
-
endChrom: number
|
|
24
|
-
startBase: number
|
|
25
|
-
endBase: number
|
|
26
|
-
validCnt: number
|
|
27
|
-
minVal: number
|
|
28
|
-
maxVal: number
|
|
29
|
-
sumData: number
|
|
30
|
-
sumSqData: number
|
|
31
|
-
}
|
|
32
18
|
|
|
33
19
|
interface ReadData {
|
|
34
|
-
offset:
|
|
35
|
-
length:
|
|
20
|
+
offset: number
|
|
21
|
+
length: number
|
|
36
22
|
}
|
|
37
23
|
|
|
38
24
|
interface Options {
|
|
@@ -40,115 +26,15 @@ interface Options {
|
|
|
40
26
|
request?: CoordRequest
|
|
41
27
|
}
|
|
42
28
|
|
|
43
|
-
const BIG_WIG_TYPE_GRAPH = 1
|
|
44
|
-
const BIG_WIG_TYPE_VSTEP = 2
|
|
45
|
-
const BIG_WIG_TYPE_FSTEP = 3
|
|
46
|
-
|
|
47
29
|
function coordFilter(s1: number, e1: number, s2: number, e2: number): boolean {
|
|
48
30
|
return s1 < e2 && e1 >= s2
|
|
49
31
|
}
|
|
50
32
|
|
|
51
|
-
function getParsers(isBigEndian: boolean) {
|
|
52
|
-
const le = isBigEndian ? 'big' : 'little'
|
|
53
|
-
const summaryParser = new Parser()
|
|
54
|
-
.endianess(le)
|
|
55
|
-
.uint32('chromId')
|
|
56
|
-
.uint32('start')
|
|
57
|
-
.uint32('end')
|
|
58
|
-
.uint32('validCnt')
|
|
59
|
-
.floatle('minScore')
|
|
60
|
-
.floatle('maxScore')
|
|
61
|
-
.floatle('sumData')
|
|
62
|
-
.floatle('sumSqData')
|
|
63
|
-
.saveOffset('offset')
|
|
64
|
-
|
|
65
|
-
const leafParser = new Parser()
|
|
66
|
-
.endianess(le)
|
|
67
|
-
.uint8('isLeaf')
|
|
68
|
-
.skip(1)
|
|
69
|
-
.uint16('cnt')
|
|
70
|
-
.choice({
|
|
71
|
-
tag: 'isLeaf',
|
|
72
|
-
choices: {
|
|
73
|
-
1: new Parser().endianess(le).array('blocksToFetch', {
|
|
74
|
-
length: 'cnt',
|
|
75
|
-
type: new Parser()
|
|
76
|
-
.endianess(le)
|
|
77
|
-
.uint32('startChrom')
|
|
78
|
-
.uint32('startBase')
|
|
79
|
-
.uint32('endChrom')
|
|
80
|
-
.uint32('endBase')
|
|
81
|
-
.uint64('blockOffset')
|
|
82
|
-
.uint64('blockSize')
|
|
83
|
-
.saveOffset('offset'),
|
|
84
|
-
}),
|
|
85
|
-
0: new Parser().array('recurOffsets', {
|
|
86
|
-
length: 'cnt',
|
|
87
|
-
type: new Parser()
|
|
88
|
-
.endianess(le)
|
|
89
|
-
.uint32('startChrom')
|
|
90
|
-
.uint32('startBase')
|
|
91
|
-
.uint32('endChrom')
|
|
92
|
-
.uint32('endBase')
|
|
93
|
-
.uint64('blockOffset')
|
|
94
|
-
.saveOffset('offset'),
|
|
95
|
-
}),
|
|
96
|
-
},
|
|
97
|
-
})
|
|
98
|
-
const bigBedParser = new Parser()
|
|
99
|
-
.endianess(le)
|
|
100
|
-
.uint32('chromId')
|
|
101
|
-
.int32('start')
|
|
102
|
-
.int32('end')
|
|
103
|
-
.string('rest', {
|
|
104
|
-
zeroTerminated: true,
|
|
105
|
-
})
|
|
106
|
-
.saveOffset('offset')
|
|
107
|
-
|
|
108
|
-
const bigWigParser = new Parser()
|
|
109
|
-
.endianess(le)
|
|
110
|
-
.skip(4)
|
|
111
|
-
.int32('blockStart')
|
|
112
|
-
.skip(4)
|
|
113
|
-
.uint32('itemStep')
|
|
114
|
-
.uint32('itemSpan')
|
|
115
|
-
.uint8('blockType')
|
|
116
|
-
.skip(1)
|
|
117
|
-
.uint16('itemCount')
|
|
118
|
-
.choice({
|
|
119
|
-
tag: 'blockType',
|
|
120
|
-
choices: {
|
|
121
|
-
[BIG_WIG_TYPE_FSTEP]: new Parser().array('items', {
|
|
122
|
-
length: 'itemCount',
|
|
123
|
-
type: new Parser().floatle('score'),
|
|
124
|
-
}),
|
|
125
|
-
[BIG_WIG_TYPE_VSTEP]: new Parser().array('items', {
|
|
126
|
-
length: 'itemCount',
|
|
127
|
-
type: new Parser().endianess(le).int32('start').floatle('score'),
|
|
128
|
-
}),
|
|
129
|
-
[BIG_WIG_TYPE_GRAPH]: new Parser().array('items', {
|
|
130
|
-
length: 'itemCount',
|
|
131
|
-
type: new Parser()
|
|
132
|
-
.endianess(le)
|
|
133
|
-
.int32('start')
|
|
134
|
-
.int32('end')
|
|
135
|
-
.floatle('score'),
|
|
136
|
-
}),
|
|
137
|
-
},
|
|
138
|
-
})
|
|
139
|
-
return {
|
|
140
|
-
bigWigParser,
|
|
141
|
-
bigBedParser,
|
|
142
|
-
summaryParser,
|
|
143
|
-
leafParser,
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
33
|
/**
|
|
148
34
|
* View into a subset of the data in a BigWig file.
|
|
149
35
|
*
|
|
150
|
-
* Adapted by Robert Buels and Colin Diesh from bigwig.js in the Dalliance
|
|
151
|
-
* Explorer by Thomas Down.
|
|
36
|
+
* Adapted by Robert Buels and Colin Diesh from bigwig.js in the Dalliance
|
|
37
|
+
* Genome Explorer by Thomas Down.
|
|
152
38
|
* @constructs
|
|
153
39
|
*/
|
|
154
40
|
|
|
@@ -159,8 +45,8 @@ export class BlockView {
|
|
|
159
45
|
cache: new QuickLRU({ maxSize: 1000 }),
|
|
160
46
|
|
|
161
47
|
fill: async (requestData, signal) => {
|
|
162
|
-
const len =
|
|
163
|
-
const off =
|
|
48
|
+
const len = requestData.length
|
|
49
|
+
const off = requestData.offset
|
|
164
50
|
const { buffer } = await this.bbi.read(Buffer.alloc(len), 0, len, off, {
|
|
165
51
|
signal,
|
|
166
52
|
})
|
|
@@ -168,10 +54,6 @@ export class BlockView {
|
|
|
168
54
|
},
|
|
169
55
|
})
|
|
170
56
|
|
|
171
|
-
private leafParser: ReturnType<typeof getParsers>['leafParser']
|
|
172
|
-
|
|
173
|
-
private bigBedParser: ReturnType<typeof getParsers>['bigBedParser']
|
|
174
|
-
|
|
175
57
|
public constructor(
|
|
176
58
|
private bbi: GenericFilehandle,
|
|
177
59
|
private refsByName: any,
|
|
@@ -183,10 +65,6 @@ export class BlockView {
|
|
|
183
65
|
if (!(cirTreeOffset >= 0)) {
|
|
184
66
|
throw new Error('invalid cirTreeOffset!')
|
|
185
67
|
}
|
|
186
|
-
|
|
187
|
-
const parsers = getParsers(isBigEndian)
|
|
188
|
-
this.leafParser = parsers.leafParser
|
|
189
|
-
this.bigBedParser = parsers.bigBedParser
|
|
190
68
|
}
|
|
191
69
|
|
|
192
70
|
public async readWigData(
|
|
@@ -208,7 +86,7 @@ export class BlockView {
|
|
|
208
86
|
Buffer.alloc(48),
|
|
209
87
|
0,
|
|
210
88
|
48,
|
|
211
|
-
|
|
89
|
+
cirTreeOffset,
|
|
212
90
|
opts,
|
|
213
91
|
)
|
|
214
92
|
}
|
|
@@ -218,35 +96,84 @@ export class BlockView {
|
|
|
218
96
|
: buffer.readUInt32LE(4)
|
|
219
97
|
let blocksToFetch: any[] = []
|
|
220
98
|
let outstanding = 0
|
|
99
|
+
const le = true
|
|
221
100
|
|
|
222
101
|
const cirFobRecur2 = (
|
|
223
102
|
cirBlockData: Buffer,
|
|
224
|
-
|
|
103
|
+
offset2: number,
|
|
225
104
|
level: number,
|
|
226
105
|
) => {
|
|
227
106
|
try {
|
|
228
|
-
const data = cirBlockData.subarray(
|
|
229
|
-
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
107
|
+
const data = cirBlockData.subarray(offset2)
|
|
108
|
+
|
|
109
|
+
const b = data
|
|
110
|
+
const dataView = new DataView(b.buffer, b.byteOffset, b.length)
|
|
111
|
+
let offset = 0
|
|
112
|
+
|
|
113
|
+
const isLeaf = dataView.getUint8(offset)
|
|
114
|
+
offset += 2 // 1 skip
|
|
115
|
+
const cnt = dataView.getUint16(offset, le)
|
|
116
|
+
offset += 2
|
|
117
|
+
if (isLeaf === 1) {
|
|
118
|
+
const blocksToFetch2 = []
|
|
119
|
+
for (let i = 0; i < cnt; i++) {
|
|
120
|
+
const startChrom = dataView.getUint32(offset, le)
|
|
121
|
+
offset += 4
|
|
122
|
+
const startBase = dataView.getUint32(offset, le)
|
|
123
|
+
offset += 4
|
|
124
|
+
const endChrom = dataView.getUint32(offset, le)
|
|
125
|
+
offset += 4
|
|
126
|
+
const endBase = dataView.getUint32(offset, le)
|
|
127
|
+
offset += 4
|
|
128
|
+
const blockOffset = Number(dataView.getBigUint64(offset, le))
|
|
129
|
+
offset += 8
|
|
130
|
+
const blockSize = Number(dataView.getBigUint64(offset, le))
|
|
131
|
+
offset += 8
|
|
132
|
+
blocksToFetch2.push({
|
|
133
|
+
startChrom,
|
|
134
|
+
startBase,
|
|
135
|
+
endBase,
|
|
136
|
+
endChrom,
|
|
137
|
+
blockOffset,
|
|
138
|
+
blockSize,
|
|
139
|
+
offset,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
235
142
|
blocksToFetch = blocksToFetch.concat(
|
|
236
|
-
|
|
143
|
+
blocksToFetch2
|
|
237
144
|
.filter(f => filterFeats(f))
|
|
238
145
|
.map(l => ({
|
|
239
146
|
offset: l.blockOffset,
|
|
240
147
|
length: l.blockSize,
|
|
241
148
|
})),
|
|
242
149
|
)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
150
|
+
} else if (isLeaf === 0) {
|
|
151
|
+
const recurOffsets = []
|
|
152
|
+
for (let i = 0; i < cnt; i++) {
|
|
153
|
+
const startChrom = dataView.getUint32(offset, le)
|
|
154
|
+
offset += 4
|
|
155
|
+
const startBase = dataView.getUint32(offset, le)
|
|
156
|
+
offset += 4
|
|
157
|
+
const endChrom = dataView.getUint32(offset, le)
|
|
158
|
+
offset += 4
|
|
159
|
+
const endBase = dataView.getUint32(offset, le)
|
|
160
|
+
offset += 4
|
|
161
|
+
const blockOffset = Number(dataView.getBigUint64(offset, le))
|
|
162
|
+
offset += 8
|
|
163
|
+
recurOffsets.push({
|
|
164
|
+
startChrom,
|
|
165
|
+
startBase,
|
|
166
|
+
endChrom,
|
|
167
|
+
endBase,
|
|
168
|
+
blockOffset,
|
|
169
|
+
offset,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
const recurOffsets2 = recurOffsets
|
|
246
173
|
.filter(f => filterFeats(f))
|
|
247
|
-
.map(l =>
|
|
248
|
-
if (
|
|
249
|
-
cirFobRecur(
|
|
174
|
+
.map(l => l.blockOffset)
|
|
175
|
+
if (recurOffsets2.length > 0) {
|
|
176
|
+
cirFobRecur(recurOffsets2, level + 1)
|
|
250
177
|
}
|
|
251
178
|
}
|
|
252
179
|
} catch (e) {
|
|
@@ -254,7 +181,12 @@ export class BlockView {
|
|
|
254
181
|
}
|
|
255
182
|
}
|
|
256
183
|
|
|
257
|
-
const filterFeats = (b:
|
|
184
|
+
const filterFeats = (b: {
|
|
185
|
+
startChrom: number
|
|
186
|
+
startBase: number
|
|
187
|
+
endChrom: number
|
|
188
|
+
endBase: number
|
|
189
|
+
}) => {
|
|
258
190
|
const { startChrom, startBase, endChrom, endBase } = b
|
|
259
191
|
return (
|
|
260
192
|
(startChrom < chrId || (startChrom === chrId && startBase <= end)) &&
|
|
@@ -296,13 +228,19 @@ export class BlockView {
|
|
|
296
228
|
outstanding += offset.length
|
|
297
229
|
|
|
298
230
|
// Upper bound on size, based on a completely full leaf node.
|
|
299
|
-
const maxCirBlockSpan = 4 +
|
|
231
|
+
const maxCirBlockSpan = 4 + cirBlockSize * 32
|
|
300
232
|
let spans = new Range([
|
|
301
|
-
{
|
|
233
|
+
{
|
|
234
|
+
min: offset[0],
|
|
235
|
+
max: offset[0] + maxCirBlockSpan,
|
|
236
|
+
},
|
|
302
237
|
])
|
|
303
238
|
for (let i = 1; i < offset.length; i += 1) {
|
|
304
239
|
const blockSpan = new Range([
|
|
305
|
-
{
|
|
240
|
+
{
|
|
241
|
+
min: offset[i],
|
|
242
|
+
max: offset[i] + maxCirBlockSpan,
|
|
243
|
+
},
|
|
306
244
|
])
|
|
307
245
|
spans = spans.union(blockSpan)
|
|
308
246
|
}
|
|
@@ -320,19 +258,15 @@ export class BlockView {
|
|
|
320
258
|
}
|
|
321
259
|
|
|
322
260
|
private parseSummaryBlock(
|
|
323
|
-
|
|
261
|
+
b: Buffer,
|
|
324
262
|
startOffset: number,
|
|
325
263
|
request?: CoordRequest,
|
|
326
264
|
) {
|
|
327
265
|
const features = [] as any[]
|
|
328
266
|
let offset = startOffset
|
|
329
267
|
|
|
330
|
-
const dataView = new DataView(
|
|
331
|
-
|
|
332
|
-
buffer.byteOffset,
|
|
333
|
-
buffer.length,
|
|
334
|
-
)
|
|
335
|
-
while (offset < buffer.byteLength) {
|
|
268
|
+
const dataView = new DataView(b.buffer, b.byteOffset, b.length)
|
|
269
|
+
while (offset < b.byteLength) {
|
|
336
270
|
// this was extracted from looking at the runtime code generated by
|
|
337
271
|
// binary-parser
|
|
338
272
|
const chromId = dataView.getUint32(offset, true)
|
|
@@ -381,11 +315,32 @@ export class BlockView {
|
|
|
381
315
|
) {
|
|
382
316
|
const items = [] as Feature[]
|
|
383
317
|
let currOffset = startOffset
|
|
318
|
+
const le = true
|
|
319
|
+
const b = data
|
|
320
|
+
const dataView = new DataView(b.buffer, b.byteOffset, b.length)
|
|
384
321
|
while (currOffset < data.byteLength) {
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
322
|
+
const c2 = currOffset
|
|
323
|
+
const chromId = dataView.getUint32(currOffset, le)
|
|
324
|
+
currOffset += 4
|
|
325
|
+
const start = dataView.getInt32(currOffset, le)
|
|
326
|
+
currOffset += 4
|
|
327
|
+
const end = dataView.getInt32(currOffset, le)
|
|
328
|
+
currOffset += 4
|
|
329
|
+
let i = currOffset
|
|
330
|
+
for (; i < data.length; i++) {
|
|
331
|
+
if (data[i] === 0) {
|
|
332
|
+
break
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const rest = data.subarray(currOffset, i).toString()
|
|
336
|
+
currOffset = i + 1
|
|
337
|
+
items.push({
|
|
338
|
+
chromId,
|
|
339
|
+
start,
|
|
340
|
+
end,
|
|
341
|
+
rest,
|
|
342
|
+
uniqueId: `bb-${offset + c2}`,
|
|
343
|
+
})
|
|
389
344
|
}
|
|
390
345
|
|
|
391
346
|
return request
|
|
@@ -398,7 +353,7 @@ export class BlockView {
|
|
|
398
353
|
private parseBigWigBlock(
|
|
399
354
|
buffer: Buffer,
|
|
400
355
|
startOffset: number,
|
|
401
|
-
|
|
356
|
+
req?: CoordRequest,
|
|
402
357
|
) {
|
|
403
358
|
const b = buffer.subarray(startOffset)
|
|
404
359
|
|
|
@@ -425,7 +380,11 @@ export class BlockView {
|
|
|
425
380
|
offset += 4
|
|
426
381
|
const score = dataView.getFloat32(offset, true)
|
|
427
382
|
offset += 4
|
|
428
|
-
items[i] = {
|
|
383
|
+
items[i] = {
|
|
384
|
+
start,
|
|
385
|
+
end,
|
|
386
|
+
score,
|
|
387
|
+
}
|
|
429
388
|
}
|
|
430
389
|
break
|
|
431
390
|
}
|
|
@@ -435,7 +394,11 @@ export class BlockView {
|
|
|
435
394
|
offset += 4
|
|
436
395
|
const score = dataView.getFloat32(offset, true)
|
|
437
396
|
offset += 4
|
|
438
|
-
items[i] = {
|
|
397
|
+
items[i] = {
|
|
398
|
+
score,
|
|
399
|
+
start,
|
|
400
|
+
end: start + itemSpan,
|
|
401
|
+
}
|
|
439
402
|
}
|
|
440
403
|
break
|
|
441
404
|
}
|
|
@@ -444,22 +407,24 @@ export class BlockView {
|
|
|
444
407
|
const score = dataView.getFloat32(offset, true)
|
|
445
408
|
offset += 4
|
|
446
409
|
const start = blockStart + i * itemStep
|
|
447
|
-
items[i] = {
|
|
410
|
+
items[i] = {
|
|
411
|
+
score,
|
|
412
|
+
start,
|
|
413
|
+
end: start + itemSpan,
|
|
414
|
+
}
|
|
448
415
|
}
|
|
449
416
|
break
|
|
450
417
|
}
|
|
451
418
|
}
|
|
452
419
|
|
|
453
|
-
return
|
|
454
|
-
? items.filter((f
|
|
455
|
-
coordFilter(f.start, f.end, request.start, request.end),
|
|
456
|
-
)
|
|
420
|
+
return req
|
|
421
|
+
? items.filter(f => coordFilter(f.start, f.end, req.start, req.end))
|
|
457
422
|
: items
|
|
458
423
|
}
|
|
459
424
|
|
|
460
425
|
public async readFeatures(
|
|
461
426
|
observer: Observer<Feature[]>,
|
|
462
|
-
blocks: { offset:
|
|
427
|
+
blocks: { offset: number; length: number }[],
|
|
463
428
|
opts: Options = {},
|
|
464
429
|
) {
|
|
465
430
|
try {
|
package/src/range.ts
CHANGED
package/src/util.ts
CHANGED
|
@@ -6,26 +6,23 @@ export class AbortError extends Error {
|
|
|
6
6
|
this.code = 'ERR_ABORTED'
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
+
|
|
10
|
+
interface Block {
|
|
11
|
+
offset: number
|
|
12
|
+
length: number
|
|
13
|
+
}
|
|
9
14
|
// sort blocks by file offset and
|
|
10
15
|
// group blocks that are within 2KB of eachother
|
|
11
|
-
export function groupBlocks(blocks:
|
|
12
|
-
blocks.sort((b0, b1) =>
|
|
16
|
+
export function groupBlocks(blocks: Block[]) {
|
|
17
|
+
blocks.sort((b0, b1) => b0.offset - b1.offset)
|
|
13
18
|
|
|
14
19
|
const blockGroups = []
|
|
15
|
-
let lastBlock
|
|
16
|
-
let lastBlockEnd
|
|
20
|
+
let lastBlock: (Block & { blocks: Block[] }) | undefined
|
|
21
|
+
let lastBlockEnd: number | undefined
|
|
17
22
|
for (const block of blocks) {
|
|
18
|
-
if (
|
|
19
|
-
lastBlock
|
|
20
|
-
|
|
21
|
-
Number(block.offset) - lastBlockEnd <= 2000
|
|
22
|
-
) {
|
|
23
|
-
lastBlock.length = BigInt(
|
|
24
|
-
Number(lastBlock.length) +
|
|
25
|
-
Number(block.length) -
|
|
26
|
-
lastBlockEnd +
|
|
27
|
-
Number(block.offset),
|
|
28
|
-
)
|
|
23
|
+
if (lastBlock && lastBlockEnd && block.offset - lastBlockEnd <= 2000) {
|
|
24
|
+
lastBlock.length =
|
|
25
|
+
lastBlock.length + block.length - lastBlockEnd + block.offset
|
|
29
26
|
lastBlock.blocks.push(block)
|
|
30
27
|
} else {
|
|
31
28
|
blockGroups.push(
|
|
@@ -36,17 +33,16 @@ export function groupBlocks(blocks: { offset: bigint; length: bigint }[]) {
|
|
|
36
33
|
}),
|
|
37
34
|
)
|
|
38
35
|
}
|
|
39
|
-
lastBlockEnd =
|
|
36
|
+
lastBlockEnd = lastBlock.offset + lastBlock.length
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
return blockGroups
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
/**
|
|
46
|
-
* Properly check if the given AbortSignal is aborted.
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* with a `code` attribute set to `ERR_ABORTED`.
|
|
43
|
+
* Properly check if the given AbortSignal is aborted. Per the standard, if the
|
|
44
|
+
* signal reads as aborted, this function throws either a DOMException
|
|
45
|
+
* AbortError, or a regular error with a `code` attribute set to `ERR_ABORTED`.
|
|
50
46
|
*
|
|
51
47
|
* For convenience, passing `undefined` is a no-op
|
|
52
48
|
*
|
|
@@ -59,7 +55,6 @@ export function checkAbortSignal(signal?: AbortSignal): void {
|
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
if (signal.aborted) {
|
|
62
|
-
// console.log('bam aborted!')
|
|
63
58
|
if (typeof DOMException === 'undefined') {
|
|
64
59
|
const e = new AbortError('aborted')
|
|
65
60
|
e.code = 'ERR_ABORTED'
|