@solid/community-server
Version:
Community Solid Server: an open and modular implementation of the Solid specifications
96 lines • 3.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SliceStream = void 0;
const node_stream_1 = require("node:stream");
const RangeNotSatisfiedHttpError_1 = require("./errors/RangeNotSatisfiedHttpError");
const StreamUtil_1 = require("./StreamUtil");
/**
* A stream that slices a part out of another stream.
* `start` and `end` are inclusive.
* If `end` is not defined it is until the end of the stream.
*
* Negative `start` values can be used to instead slice that many streams off the end of the stream.
* This requires the `size` field to be defined.
*
* Both object and non-object streams are supported.
* This needs to be explicitly specified,
* as the class makes no assumptions based on the object mode of the source stream.
*/
class SliceStream extends node_stream_1.Transform {
source;
remainingSkip;
remainingRead;
constructor(source, options) {
super(options);
let start = options.start;
const end = options.end ?? Number.POSITIVE_INFINITY;
if (options.start < 0) {
if (typeof options.size === 'number') {
// `start` is a negative number here so need to add
start = options.size + start;
}
else {
throw new RangeNotSatisfiedHttpError_1.RangeNotSatisfiedHttpError('Slicing data at the end of a stream requires a known size.');
}
}
if (start >= end) {
throw new RangeNotSatisfiedHttpError_1.RangeNotSatisfiedHttpError('Range start should be less than end.');
}
// Not using `end` variable as that could be infinity
if (typeof options.end === 'number' && typeof options.size === 'number' && options.end >= options.size) {
throw new RangeNotSatisfiedHttpError_1.RangeNotSatisfiedHttpError('Range end should be less than the total size.');
}
this.remainingSkip = start;
// End value is inclusive
this.remainingRead = end - options.start + 1;
this.source = source;
(0, StreamUtil_1.pipeSafely)(source, this);
}
// eslint-disable-next-line ts/naming-convention
_transform(chunk, encoding, callback) {
this.source.pause();
if (this.writableObjectMode) {
this.objectSlice(chunk);
}
else {
this.binarySlice(chunk);
}
this.source.resume();
callback();
}
binarySlice(chunk) {
let length = chunk.length;
if (this.remainingSkip > 0) {
chunk = chunk.subarray(this.remainingSkip);
this.remainingSkip -= length - chunk.length;
length = chunk.length;
}
if (length > 0 && this.remainingSkip <= 0) {
chunk = chunk.subarray(0, this.remainingRead);
this.push(chunk);
this.remainingRead -= length;
this.checkEnd();
}
}
objectSlice(chunk) {
if (this.remainingSkip > 0) {
this.remainingSkip -= 1;
}
else {
this.remainingRead -= 1;
this.push(chunk);
this.checkEnd();
}
}
/**
* Stop piping the source stream and close everything once the slice is finished.
*/
checkEnd() {
if (this.remainingRead <= 0) {
this.source.unpipe(this);
this.end();
}
}
}
exports.SliceStream = SliceStream;
//# sourceMappingURL=SliceStream.js.map