Skip to content

Commit

Permalink
WIP 5
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Sep 22, 2019
1 parent 8ee53dc commit fef31d7
Showing 1 changed file with 58 additions and 41 deletions.
99 changes: 58 additions & 41 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,54 +164,71 @@ class ChopStream extends Writable {
throw new Error('`._read()` called on output stream which has already ended');
}

// TODO Is this required? Currently how many bytes is requested is ignored
this._outReadBytes += bytes;

// Push any content from buffer
const {bufferEnd, _outEnd: outEnd} = this;
let outPos = this._outPos;
if (bufferEnd > outPos) {
let chunkStart = this.bufferStart;
// If no content in buffer to push, flag stream as flowing so future writes
// are pushed to output stream and exit
const {bufferEnd, _outPos: outPos} = this;
if (bufferEnd <= outPos) {
this._outFlowing = true;
return;
}

// Error if gap between what's requested and what's in buffer
if (chunkStart > outPos) {
throw new Error(`Buffer starts at ${chunkStart} but need from ${outPos}`);
}
// Error if gap between what's requested and what's in buffer
let chunkStart = this.bufferStart;
if (chunkStart > outPos) {
throw new Error(`Buffer starts at ${chunkStart} but need from ${outPos}`);
}

// Push chunks from buffer
for (let chunk of this._buffers) {
let chunkLength = chunk.length,
chunkEnd = chunkStart + chunkLength;

// If chunk is before desired, skip
if (chunkEnd <= outPos) {
chunkStart += chunkLength;
continue;
}

// If chunk only wanted in part, cut down to just part wanted
if (chunkEnd > outEnd) {
// Want start of chunk only
chunkLength = outEnd - chunkStart;
chunkEnd = outEnd;
chunk = chunk.slice(0, chunkLength);
} else if (chunkStart < outPos) {
// Want end of chunk only
const splitAt = outPos - chunkStart;
chunkLength -= splitAt;
chunkStart = outPos;
chunk = chunk.slice(splitAt);
}

// Push chunk
const flowing = this._pushChunk(chunk);
if (!flowing) return;
chunkStart += chunkLength;
outPos += chunkLength;
// Locate first chunk from buffer to push
// TODO This loop can be avoided by caching `index` between calls to `._readChunk()`
const {_outEnd: outEnd, _buffers: buffers} = this;
let index = 0,
chunk,
chunkEnd;
while (true) { // eslint-disable-line no-constant-condition
// Get next chunk from buffer
chunk = buffers[index];
chunkEnd = chunkStart + chunk.length;

// Stop searching if found first chunk
if (chunkStart === outPos) break;

// Skip chunk if before what's wanted
if (chunkEnd <= outPos) {
chunkStart = chunkEnd;
index++;
// NB No need to check if index is out of bounds as already checked above
// that buffer does contain data that's wanted
continue;
}

// Only part of chunk wanted - split off only what's required
chunk = chunk.slice(outPos - chunkStart);
chunkStart = outPos;
}

// Flag stream as flowing so future writes are pushed to output stream
this._outFlowing = true;
// Push chunks
while (true) { // eslint-disable-line no-constant-condition
// If only part of chunk required, split it
if (chunkEnd > outEnd) {
chunkEnd = outEnd;
chunk = chunk.slice(0, outEnd - chunkStart);
}

// Push chunk
const flowing = this._pushChunk(chunk);
if (!flowing) break;

// Get next chunk from buffer
index++;
if (index === buffers.length) break;

chunkStart = chunkEnd;
chunk = buffers[index];
chunkEnd = chunkStart + chunk.length;
}
}

/**
Expand Down

0 comments on commit fef31d7

Please sign in to comment.