52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
import type { Readable, Writable } from "stream";
|
|
|
|
const MAX_UINT32 = 2 ** 32 - 1;
|
|
|
|
/** Write one or more NAR strings to the output. */
|
|
export const writeNarStrings = (out: Writable, ...input: string[]) => {
|
|
let size = 0;
|
|
const bufs = input.map((str) => {
|
|
const buf = Buffer.from(str);
|
|
// TODO: Support up to MAX_SAFE_INTEGER
|
|
if (buf.byteLength > MAX_UINT32) {
|
|
throw Error(`NAR string too long: ${buf.byteLength}`);
|
|
}
|
|
size += 8 + Math.ceil(buf.byteLength / 8) * 8;
|
|
return buf;
|
|
});
|
|
|
|
const res = Buffer.alloc(size);
|
|
let pos = 0;
|
|
for (const buf of bufs) {
|
|
res.writeUInt32LE(buf.byteLength, pos);
|
|
buf.copy(res, pos + 8);
|
|
pos += 8 + Math.ceil(buf.byteLength / 8) * 8;
|
|
}
|
|
|
|
out.write(res);
|
|
};
|
|
|
|
/** Write the contents of a stream as a NAR string to the output. */
|
|
export const writeNarStream = async (
|
|
out: Writable,
|
|
size: number,
|
|
input: Readable,
|
|
) => {
|
|
// TODO: Support up to MAX_SAFE_INTEGER
|
|
if (size > MAX_UINT32) {
|
|
throw Error(`NAR string too long: ${size}`);
|
|
}
|
|
const sizeBuf = Buffer.alloc(8);
|
|
sizeBuf.writeUInt32LE(size);
|
|
out.write(sizeBuf);
|
|
|
|
for await (const chunk of input) {
|
|
out.write(chunk);
|
|
}
|
|
|
|
const padding = 8 - (size % 8);
|
|
if (padding !== 8) {
|
|
out.write(Buffer.alloc(padding));
|
|
}
|
|
};
|