Skip to content

Commit

Permalink
Rewrote reading from buffers to use a DataView.
Browse files Browse the repository at this point in the history
  • Loading branch information
iwoplaza committed Dec 17, 2024
1 parent c3c6674 commit e842da5
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 49 deletions.
17 changes: 0 additions & 17 deletions packages/typed-binary/src/io/bufferIOBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,7 @@ export type BufferIOOptions = {

export class BufferIOBase {
protected readonly dataView: DataView;
protected readonly uint8View: Uint8Array;
protected readonly helperInt32View: Int32Array;
protected readonly helperUint32View: Uint32Array;
protected readonly helperUint16View: Uint16Array;
protected readonly helperFloat32View: Float32Array;
protected readonly helperByteView: Uint8Array;
protected readonly switchEndianness: boolean;
protected readonly littleEndian: boolean;

protected byteOffset = 0;

public readonly endianness: Endianness;
Expand All @@ -35,22 +27,13 @@ export class BufferIOBase {

const systemEndianness = getSystemEndianness();
this.endianness = endianness === 'system' ? systemEndianness : endianness;
this.switchEndianness = this.endianness !== systemEndianness;
this.littleEndian = this.endianness === 'little';

// Getting rid of the outer shell, which causes the Uint8Array line to create a copy, instead of a view.
const unwrapped = unwrapBuffer(buffer);
this.byteOffset += unwrapped.byteOffset;

this.dataView = new DataView(unwrapped.buffer);
this.uint8View = new Uint8Array(unwrapped.buffer, 0);

const helperBuffer = new ArrayBuffer(4);
this.helperInt32View = new Int32Array(helperBuffer);
this.helperUint32View = new Uint32Array(helperBuffer);
this.helperFloat32View = new Float32Array(helperBuffer);
this.helperByteView = new Uint8Array(helperBuffer);
this.helperUint16View = new Uint16Array(helperBuffer);
}

get currentByteOffset() {
Expand Down
40 changes: 17 additions & 23 deletions packages/typed-binary/src/io/bufferWriter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,53 +13,47 @@ export class BufferWriter extends BufferIOBase implements ISerialOutput {
return this._cachedTextEncoder;
}

private copyHelperToOutput(bytes: number) {
for (let i = 0; i < bytes; ++i)
this.uint8View[this.byteOffset++] =
this.helperByteView[this.switchEndianness ? bytes - 1 - i : i];
}

writeBool(value: boolean) {
this.uint8View[this.byteOffset++] = value ? 1 : 0;
this.dataView.setUint8(this.byteOffset++, value ? 1 : 0);
}

writeByte(value: number) {
this.uint8View[this.byteOffset++] = Math.floor(value) % 256;
this.dataView.setUint8(this.byteOffset++, value);
}

writeFloat16(value: number): void {
this.helperUint16View[0] = numberToFloat16(value)[0];

this.copyHelperToOutput(2);
this.dataView.setUint16(
this.byteOffset,
numberToFloat16(value),
this.littleEndian,
);
this.byteOffset += 2;
}

writeInt32(value: number) {
this.helperInt32View[0] = Math.floor(value);

this.copyHelperToOutput(4);
this.dataView.setInt32(this.byteOffset, value, this.littleEndian);
this.byteOffset += 4;
}

writeUint32(value: number) {
this.helperUint32View[0] = Math.floor(value);

this.copyHelperToOutput(4);
this.dataView.setUint32(this.byteOffset, value, this.littleEndian);
this.byteOffset += 4;
}

writeFloat32(value: number) {
this.helperFloat32View[0] = value;

this.copyHelperToOutput(4);
this.dataView.setFloat32(this.byteOffset, value, this.littleEndian);
this.byteOffset += 4;
}

writeString(value: string) {
const result = this._textEncoder.encodeInto(
value,
this.uint8View.subarray(this.byteOffset),
new Uint8Array(this.dataView.buffer, this.byteOffset),
);
this.byteOffset += result.written;

// Extra null character
this.uint8View[this.byteOffset++] = 0;
this.dataView.setUint8(this.byteOffset++, 0);
}

writeSlice(bufferView: ArrayLike<number> & ArrayBufferView): void {
Expand All @@ -72,7 +66,7 @@ export class BufferWriter extends BufferIOBase implements ISerialOutput {
);

for (const srcByte of srcU8) {
this.uint8View[this.byteOffset++] = srcByte;
this.dataView.setUint8(this.byteOffset++, srcByte);
}
}
}
14 changes: 5 additions & 9 deletions packages/typed-binary/src/io/float16converter.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
export function numberToFloat16(value: number): Uint16Array {
export function numberToFloat16(value: number): number {
// conversion according to IEEE 754 binary16 format
if (value === 0) return new Uint16Array([0]);
if (Number.isNaN(value)) return new Uint16Array([0x7e00]);
if (!Number.isFinite(value))
return new Uint16Array([value > 0 ? 0x7c00 : 0xfc00]);
if (value === 0) return 0;
if (Number.isNaN(value)) return 0x7e00;
if (!Number.isFinite(value)) return value > 0 ? 0x7c00 : 0xfc00;

const sign = value < 0 ? 1 : 0;
const absValue = Math.abs(value);
const exponent = Math.floor(Math.log2(absValue));
const mantissa = absValue / 2 ** exponent - 1;
const biasedExponent = exponent + 15;
const mantissaBits = Math.floor(mantissa * 1024);
const float16 = (sign << 15) | (biasedExponent << 10) | mantissaBits;
const uint16Array = new Uint16Array(1);
uint16Array[0] = float16;
return uint16Array;
return (sign << 15) | (biasedExponent << 10) | mantissaBits;
}

export function float16ToNumber(uint16Encoding: number): number {
Expand Down

0 comments on commit e842da5

Please sign in to comment.