@gmod/jbrowse
Version:
JBrowse - client-side genome browser
127 lines (111 loc) • 3.88 kB
JavaScript
define([
'dojo/_base/declare',
'dojo/_base/array',
'dojo/has',
'JBrowse/Util/TextIterator'
],
function( declare, array, has, TextIterator ) {
var FileBlob = declare( null,
/**
* @lends JBrowse.Model.FileBlob.prototype
*/
{
/**
* Blob of binary data fetched from a local file (with FileReader).
*
* Adapted by Robert Buels from the BlobFetchable object in the
* Dalliance Genome Explorer, which is copyright Thomas Down
* 2006-2011.
* @constructs
*/
constructor: function(b) {
this.blob = b;
this.size = b.size;
this.totalSize = b.size;
},
slice: function(start, length) {
var sliceFunc = this.blob.mozSlice || this.blob.slice || this.blob.webkitSlice;
return new FileBlob(
length ? sliceFunc.call( this.blob, start, start + length )
: sliceFunc.call( this.blob, start )
);
},
fetchLines: function( lineCallback, endCallback, failCallback ) {
var thisB = this;
this.fetch( function( data ) {
data = new Uint8Array(data);
var lineIterator = new TextIterator.FromBytes(
{ bytes: data,
// only return a partial line at the end
// if we are not operating on a slice of
// the file
returnPartialRecord: !this.end
});
var line;
while(( line = lineIterator.getline() )) {
lineCallback( line );
}
endCallback();
}, failCallback );
},
readLines: function( offset=0, length, lineCallback, endCallback, failCallback ) {
var start = this.start + offset,
end = start + length;
var skipFirst = offset != 0;
this.slice( offset, length )
.fetchLines(
function() {
// skip the first line if we have a
// nonzero offset, because it is probably
// incomplete
if( ! skipFirst )
lineCallback();
skipFirst = false;
}, endCallback, failCallback );
},
read: function( offset=0, length, callback, failCallback ) {
var start = this.start + offset,
end = start + length;
// short-circuit a read of 0 bytes here, because browsers
// actually sometimes crash if you try to read 0 bytes from
// a local file!
if (!length) {
callback(new ArrayBuffer())
return
}
this.slice( offset, length )
.fetch( callback, failCallback );
},
readBufferPromise(offset,length) {
return new Promise((resolve,reject) => {
this.read(offset, length, data => {
resolve(window.Buffer.from(data))
}, reject)
})
},
fetch: function( callback, failCallback ) {
try {
const reader = new FileReader()
reader.onloadend = ev => {
callback( reader.result )
}
reader.onerror = failCallback
reader.readAsArrayBuffer(this.blob)
} catch(e) { failCallback(e) }
},
fetchBufferPromise() {
return new Promise((resolve,reject) => {
this.fetch(data => {
resolve(window.Buffer.from(data))
}, reject)
})
},
stat(callback,failCallback) {
this.statPromise().then(callback, failCallback)
},
async statPromise() {
return { size: this.blob.size }
}
});
return FileBlob;
});