UNPKG

hic-straw

Version:

Utilities for reading .files (contact matrix files)

115 lines (96 loc) 3.65 kB
class BufferedFile { constructor(args) { this.file = args.file this.size = args.size || 64000 this.position = 0 this.bufferStart = 0 this.bufferLength = 0 this.buffer = undefined } async read(position, length) { const start = position const end = position + length const bufferStart = this.bufferStart const bufferEnd = this.bufferStart + this.bufferLength if (length > this.size) { // Request larger than max buffer size, pass through to underlying file //console.log("0") this.buffer = undefined this.bufferStart = 0 this.bufferLength = 0 return this.file.read(position, length) } if (start >= bufferStart && end <= bufferEnd) { // Request within buffer bounds //console.log("1") const sliceStart = start - bufferStart const sliceEnd = sliceStart + length return this.buffer.slice(sliceStart, sliceEnd) } else if (start < bufferStart && end > bufferStart) { // Overlap left, here for completness but this is an unexpected case in straw. We don't adjust the buffer. //console.log("2") const l1 = bufferStart - start const a1 = await this.file.read(position, l1) const l2 = length - l1 if (l2 > 0) { //this.buffer = await this.file.read(bufferStart, this.size) const a2 = this.buffer.slice(0, l2) return concatBuffers(a1, a2) } else { return a1 } } else if (start < bufferEnd && end > bufferEnd) { // Overlap right // console.log("3") const l1 = bufferEnd - start const sliceStart = this.bufferLength - l1 const a1 = this.buffer.slice(sliceStart, this.bufferLength) const l2 = length - l1 if (l2 > 0) { try { this.buffer = await this.file.read(bufferEnd, this.size) this.bufferStart = bufferEnd this.bufferLength = this.buffer.byteLength const a2 = this.buffer.slice(0, l2) return concatBuffers(a1, a2) } catch (e) { // A "unsatisfiable range" error is expected here if we overlap past the end of file if (e.code && e.code === 416) { return a1 } else { throw e } } } else { return a1 } } else { // No overlap with buffer // console.log("4") this.buffer = await this.file.read(position, this.size) this.bufferStart = position this.bufferLength = this.buffer.byteLength return this.buffer.slice(0, length) } } } /** * concatenates 2 array buffers. * Credit: https://gist.github.com/72lions/4528834 * * @private * @param {ArrayBuffers} buffer1 The first buffer. * @param {ArrayBuffers} buffer2 The second buffer. * @return {ArrayBuffers} The new ArrayBuffer created out of the two. */ var concatBuffers = function (buffer1, buffer2) { var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength); tmp.set(new Uint8Array(buffer1), 0); tmp.set(new Uint8Array(buffer2), buffer1.byteLength); return tmp.buffer; }; export default BufferedFile;