UNPKG

slice-source

Version:

A readable stream reader that reads a desired number of bytes.

92 lines (77 loc) 2.87 kB
// https://github.com/mbostock/slice-source Version 0.4.1. Copyright 2016 Mike Bostock. (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.sources = global.sources || {}, global.sources.slice = factory()); }(this, (function () { 'use strict'; var empty = new Uint8Array(0); function slice_cancel() { return this._source.cancel(); } function concat(a, b) { if (!a.length) return b; if (!b.length) return a; var c = new Uint8Array(a.length + b.length); c.set(a); c.set(b, a.length); return c; } function slice_read() { var that = this, array = that._array.subarray(that._index); return that._source.read().then(function(result) { that._array = empty; that._index = 0; return result.done ? (array.length > 0 ? {done: false, value: array} : {done: true, value: undefined}) : {done: false, value: concat(array, result.value)}; }); } function slice_slice(length) { if ((length |= 0) < 0) throw new Error("invalid length"); var that = this, index = this._array.length - this._index; // If the request fits within the remaining buffer, resolve it immediately. if (this._index + length <= this._array.length) { return Promise.resolve(this._array.subarray(this._index, this._index += length)); } // Otherwise, read chunks repeatedly until the request is fulfilled. var array = new Uint8Array(length); array.set(this._array.subarray(this._index)); return (function read() { return that._source.read().then(function(result) { // When done, it’s possible the request wasn’t fully fullfilled! // If so, the pre-allocated array is too big and needs slicing. if (result.done) { that._array = empty; that._index = 0; return index > 0 ? array.subarray(0, index) : null; } // If this chunk fulfills the request, return the resulting array. if (index + result.value.length >= length) { that._array = result.value; that._index = length - index; array.set(result.value.subarray(0, length - index), index); return array; } // Otherwise copy this chunk into the array, then read the next chunk. array.set(result.value, index); index += result.value.length; return read(); }); })(); } function slice(source) { return typeof source.slice === "function" ? source : new SliceSource(typeof source.read === "function" ? source : source.getReader()); } function SliceSource(source) { this._source = source; this._array = empty; this._index = 0; } SliceSource.prototype.read = slice_read; SliceSource.prototype.slice = slice_slice; SliceSource.prototype.cancel = slice_cancel; return slice; })));