Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 21 additions & 25 deletions packages/util/src/FlexibleBuffer.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,40 @@
type IBufferRawData = number[]

interface IBufferJson {
type: string
data: number[]
data: IBufferRawData
}

interface IFlexibleBuffer {
readonly length: number
push(value: ArrayLike<number>): this
push(value: ArrayLike<number>): void
toBuffer(): Buffer
toArray(): number[]
toArray(): IBufferRawData
clear(): void
toJSON(): IBufferJson
}

export abstract class FlexibleBuffer implements IFlexibleBuffer {
static auto(size?: number | null): FlexibleBuffer {
return typeof size === "number"
return typeof size === "number" && !isNaN(size)
? new BufferFlexibleBuffer(size)
: new ArrayFlexibleBuffer();
}

static flexible(): FlexibleBuffer {
return new ArrayFlexibleBuffer();
}
static flexible(): FlexibleBuffer { return new ArrayFlexibleBuffer(); }

static fixed(size: number): FlexibleBuffer {
return new BufferFlexibleBuffer(size);
}
static fixed(size: number): FlexibleBuffer { return new BufferFlexibleBuffer(size); }

abstract readonly length: number
abstract push(value: ArrayLike<number>): this
abstract push(value: ArrayLike<number>): void
abstract toBuffer(): Buffer
abstract toArray(): number[]
abstract toArray(): IBufferRawData
abstract clear(): void
abstract toJSON(): IBufferJson
}

class BufferFlexibleBuffer extends FlexibleBuffer {
constructor(size: number) {
constructor(readonly size: number) {
super();
this._buffer = Buffer.alloc(size);
}
Expand All @@ -48,18 +46,17 @@ class BufferFlexibleBuffer extends FlexibleBuffer {
return this._index;
}

push(value: ArrayLike<number>): this {
push(value: ArrayLike<number>) {
this._buffer.set(value, this._index);
this._index += value.length;
return this;
}

toBuffer(): Buffer {
return this._buffer;
}

toArray(): number[] {
return Array.from(this._buffer);
toArray(): IBufferRawData {
return this.toJSON().data;
}

clear(): void {
Expand All @@ -73,29 +70,28 @@ class BufferFlexibleBuffer extends FlexibleBuffer {
}

class ArrayFlexibleBuffer extends FlexibleBuffer {
private readonly _buffer: any[] = [];
private readonly _array: Uint8Array[] = [];
private _length = 0;

get length(): number {
return this._length;
}

push(value: ArrayLike<number>): this {
this._buffer.push(value);
push(value: ArrayLike<number>): void {
this._array.push(new Uint8Array(value));
this._length += value.length;
return this;
}

toBuffer(): Buffer {
return Buffer.concat(this._buffer);
return Buffer.concat(this._array, this._length);
}

toArray(): number[] {
return this._buffer;
toArray(): IBufferRawData {
return this.toJSON().data;
}

clear(): void {
this._buffer.length = 0;
this._array.length = 0;
this._length = 0;
}

Expand Down
37 changes: 31 additions & 6 deletions packages/util/src/test/FlexibleBuffer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,46 @@ import assert from "assert";
import test, { suite } from "node:test";
import { FlexibleBuffer } from "../FlexibleBuffer";

const array = [1, 2, 3];
const _array = [65, 66, 67];

suite("Array FlexibleBuffer", () => {
const buffer = FlexibleBuffer.flexible();
const flexibleBuffer = FlexibleBuffer.flexible();

test("Allow push oversized", () => {
buffer.push(array);
assert.strictEqual(buffer.length, array.length);
flexibleBuffer.push(_array);
assert.strictEqual(flexibleBuffer.length, _array.length);
});

test("Transform to buffer", () => {
assert.doesNotThrow(() => {
const buffer = flexibleBuffer.toBuffer();

assert.strictEqual(buffer.length, _array.length);

for (let i = 0; i < buffer.length; i++) {
assert.strictEqual(buffer[i], _array[i]);
}
});
});
});

suite("Buffer FlexibleBuffer", () => {
const buffer = FlexibleBuffer.fixed(1);
const fixedBuffer = FlexibleBuffer.fixed(3);

test("Allow pushing a list with a size within the limit", () => {
assert.doesNotThrow(() => fixedBuffer.push(_array));
assert.strictEqual(fixedBuffer.length, _array.length);
});

test("Deny push oversized", () => {
assert.throws(() => buffer.push(array));
assert.throws(() => fixedBuffer.push(_array));
});

test("Transform to array", () => {
assert.doesNotThrow(() => {
const array = fixedBuffer.toArray();
assert.strictEqual(array.length, _array.length);
assert.deepStrictEqual(array, _array);
});
});
});
Loading