reduct-js
Version:
ReductStore Client SDK for Javascript/NodeJS/Typescript
63 lines (62 loc) • 1.79 kB
JavaScript
//#region src/batch/Common.ts
function createBatchStreamReader(head, body) {
let reader = null;
if (!head && body instanceof ReadableStream) reader = body.getReader();
let leftover = null;
const makeEmptyStream = () => new ReadableStream({ start(ctrl) {
ctrl.close();
} });
async function readExactly(len) {
if (!reader) throw new Error("Reader is not available");
const parts = [];
let filled = 0;
if (leftover) {
const take = Math.min(leftover.length, len);
parts.push(leftover.subarray(0, take));
filled += take;
leftover = leftover.length > take ? leftover.subarray(take) : null;
}
while (filled < len) {
const { value, done } = await reader.read();
if (done) throw new Error("Unexpected EOF while batching records");
const need = len - filled;
if (value.length > need) {
parts.push(value.subarray(0, need));
leftover = value.subarray(need);
filled = len;
} else {
parts.push(value);
filled += value.length;
}
}
const out = new Uint8Array(len);
let off = 0;
for (const p of parts) {
out.set(p, off);
off += p.length;
}
return out;
}
async function createStream(byteLen, isLastInBatch) {
if (!reader) return makeEmptyStream();
if (isLastInBatch) return new ReadableStream({
start(ctrl) {
if (leftover) ctrl.enqueue(leftover);
},
async pull(ctrl) {
if (!reader) throw new Error("Reader is not available");
const { value, done: isDone } = await reader.read();
if (value) ctrl.enqueue(value);
if (isDone) ctrl.close();
}
});
const bytes = await readExactly(byteLen);
return new ReadableStream({ start(ctrl) {
if (bytes.length) ctrl.enqueue(bytes);
ctrl.close();
} });
}
return { createStream };
}
//#endregion
export { createBatchStreamReader };