68 lines
1.7 KiB
TypeScript
68 lines
1.7 KiB
TypeScript
import { Bytes, BytesLike, underlying } from "./bytes";
|
|
|
|
export type IOList = number | BytesLike | IOList[] | false | CountedIOList;
|
|
|
|
class CountedIOList {
|
|
value: IOList;
|
|
length: number;
|
|
|
|
constructor(i: IOList) {
|
|
this.value = i;
|
|
this.length = iolistLength(i);
|
|
}
|
|
}
|
|
|
|
export function pushByte(i: IOList, b: number): IOList {
|
|
if (Array.isArray(i)) {
|
|
i.push(b);
|
|
return i;
|
|
} else {
|
|
return [i, b];
|
|
}
|
|
}
|
|
|
|
export function append(i: IOList, j: IOList): IOList {
|
|
if (i === false) return j;
|
|
if (j === false) return i;
|
|
return [i, j];
|
|
}
|
|
|
|
export function iolistLength(i: IOList, acc = 0): number {
|
|
if (typeof(i) === 'number') return acc + 1;
|
|
if (i === false) return acc;
|
|
if (Array.isArray(i)) return i.reduce<number>((acc, j) => iolistLength(j, acc), acc);
|
|
if (i instanceof CountedIOList) return acc + i.length;
|
|
return acc + i.length;
|
|
}
|
|
|
|
export function countIOList(i: IOList): CountedIOList {
|
|
if (i instanceof CountedIOList) return i;
|
|
return new CountedIOList(i);
|
|
}
|
|
|
|
export function ioListBytes(i: IOList): Bytes {
|
|
if (i instanceof Bytes) return i;
|
|
const buffer = new Bytes(iolistLength(i));
|
|
|
|
function fill(i: IOList, offset: number): number {
|
|
while (i instanceof CountedIOList) i = i.value;
|
|
if (typeof(i) === 'number') {
|
|
buffer._view[offset] = i;
|
|
return offset + 1;
|
|
}
|
|
if (i === false) {
|
|
return offset;
|
|
}
|
|
if (Array.isArray(i)) {
|
|
i.forEach(j => offset = fill(j, offset));
|
|
return offset;
|
|
}
|
|
const bs = underlying(i);
|
|
buffer._view.set(bs, offset);
|
|
return offset + bs.length;
|
|
}
|
|
|
|
fill(i, 0);
|
|
return buffer;
|
|
}
|