univ-conv
Version:
The universal binary and text converter
200 lines • 7.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReadableStreamConverter = exports.createPartialReadableStream = void 0;
const AbstractConverter_1 = require("./AbstractConverter");
const core_1 = require("./core");
const Environment_1 = require("./Environment");
function createReadableStream(u8) {
return new ReadableStream({
start: (controller) => {
controller.enqueue(u8);
},
});
}
function createPartialReadableStream(source, startEnd) {
const reader = source.getReader();
const start = startEnd.start;
const end = startEnd.end ?? Number.MAX_SAFE_INTEGER;
return new ReadableStream({
start: async (controller) => {
let iStart = 0;
let res;
do {
res = await reader.read();
const value = res.value;
if (value) {
const u8 = value;
const length = u8.byteLength;
const iEnd = iStart + length;
const u8End = (iEnd < end ? iEnd : end) - iStart;
let chunk;
if (iStart <= start && start < iEnd) {
chunk = u8.subarray(start - iStart, u8End);
}
else if (start < iStart && iStart < end) {
chunk = u8.subarray(0, u8End);
}
if (chunk) {
controller.enqueue(chunk);
}
iStart += length;
}
} while (!res.done && iStart < end);
controller.close();
reader.releaseLock();
(0, Environment_1.closeStream)(source);
},
cancel: (e) => {
reader.releaseLock();
(0, Environment_1.closeStream)(source, e);
},
});
}
exports.createPartialReadableStream = createPartialReadableStream;
function createReadableStreamOfReader(readable, options) {
const startEnd = (0, core_1.getStartEnd)(options);
const start = startEnd.start;
const end = startEnd.end ?? Number.MAX_SAFE_INTEGER;
const bufferSize = options.bufferSize;
const converter = (0, AbstractConverter_1._)()._of("uint8array");
let iStart = 0;
return new ReadableStream({
start: async (controller) => {
await (0, Environment_1.handleReadable)(readable, async (value) => {
const u8 = await converter.from(value, { bufferSize });
const size = u8.byteLength;
const iEnd = iStart + size;
const u8End = (iEnd < end ? iEnd : end) - iStart;
let chunk;
if (iStart <= start && start < iEnd) {
chunk = u8.subarray(start - iStart, u8End);
}
else if (start < iStart && iStart < end) {
chunk = u8.subarray(0, u8End);
}
if (chunk) {
controller.enqueue(chunk);
}
iStart += size;
return iStart < end;
});
},
cancel: (err) => {
readable.destroy(err);
},
});
}
class ReadableStreamConverter extends AbstractConverter_1.AbstractConverter {
constructor() {
super(...arguments);
this.type = "readablestream";
}
empty() {
return new ReadableStream({
start: (converter) => {
converter.enqueue(core_1.EMPTY_UINT8_ARRAY);
converter.close();
},
});
}
is(input) {
return (0, Environment_1.isReadableStream)(input);
}
async _from(input, options) {
if (typeof input === "string" && options.inputStringType === "url") {
if (input.startsWith("http:") || input.startsWith("https:")) {
const resp = await fetch(input);
if ((0, AbstractConverter_1._)().is("readable", resp.body, options)) {
input = resp.body;
}
else {
input = resp.body;
}
}
else if (input.startsWith("file:") && Environment_1.fileURLToReadable) {
input = await (0, Environment_1.fileURLToReadable)(input);
}
}
if ((0, AbstractConverter_1._)().is("readable", input, options)) {
return createReadableStreamOfReader(input, options);
}
if (Environment_1.hasStreamOnBlob) {
if ((0, AbstractConverter_1._)().is("blob", input, options)) {
input = input.stream();
}
else {
const blob = await (0, AbstractConverter_1._)().convert("blob", input, options);
input = blob.stream();
}
}
if (this.is(input)) {
return createPartialReadableStream(input, await this._getStartEnd(input, options));
}
const u8 = await (0, AbstractConverter_1._)().convert("uint8array", input, options);
const { start, end } = (0, core_1.getStartEnd)(options, u8.byteLength);
return createReadableStream(u8.slice(start, end));
}
_getStartEnd(_input, options) {
return Promise.resolve((0, core_1.getStartEnd)(options));
}
_isEmpty() {
return false;
}
_merge(streams) {
const end = streams.length;
const process = (controller, i) => {
if (i < end) {
const stream = streams[i];
(0, Environment_1.handleReadableStream)(stream, (chunk) => {
controller.enqueue(chunk);
return Promise.resolve(true);
})
.then(() => process(controller, ++i))
.catch((e) => {
controller.error(e);
for (let j = i; j < end; j++) {
const s = streams[j];
(0, Environment_1.closeStream)(s);
}
});
}
else {
controller.close();
}
};
return Promise.resolve(new ReadableStream({
start: (converter) => {
process(converter, 0);
},
}));
}
_size() {
throw new Error("Cannot get size of ReadableStream");
}
async _toArrayBuffer(input, options) {
const u8 = await this._toUint8Array(input, options);
return u8.buffer.slice(u8.byteOffset, u8.byteOffset + u8.byteLength);
}
async _toBase64(input, options) {
const opts = { bufferSize: options.bufferSize };
const t = Environment_1.isBrowser ? "blob" : "uint8array";
const convertd = await (0, AbstractConverter_1._)().convert(t, input, opts);
return await (0, AbstractConverter_1._)()._of(t).toBase64(convertd, options);
}
async _toText(input, options) {
const opts = { bufferSize: options.bufferSize };
const t = Environment_1.isBrowser ? "blob" : "uint8array";
const convertd = await (0, AbstractConverter_1._)().convert(t, input, opts);
return await (0, AbstractConverter_1._)()._of(t).toText(convertd, options);
}
async _toUint8Array(input, options) {
const chunks = [];
await (0, Environment_1.handleReadableStream)(input, async (chunk) => {
chunks.push(chunk);
return Promise.resolve(true);
});
return await (0, AbstractConverter_1._)()._of("uint8array").merge(chunks, options);
}
}
exports.ReadableStreamConverter = ReadableStreamConverter;
//# sourceMappingURL=ReadableStreamConverter.js.map