diff --git a/packages/typed-binary/src/io/bufferIOBase.ts b/packages/typed-binary/src/io/bufferIOBase.ts index 86b5815..02d5fab 100644 --- a/packages/typed-binary/src/io/bufferIOBase.ts +++ b/packages/typed-binary/src/io/bufferIOBase.ts @@ -14,14 +14,8 @@ export type BufferIOOptions = { }; export class BufferIOBase { - 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 dataView: DataView; + protected readonly littleEndian: boolean; protected byteOffset = 0; public readonly endianness: Endianness; @@ -33,20 +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.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); + this.dataView = new DataView(unwrapped.buffer); } get currentByteOffset() { diff --git a/packages/typed-binary/src/io/bufferReader.ts b/packages/typed-binary/src/io/bufferReader.ts index c845592..19e8c2f 100644 --- a/packages/typed-binary/src/io/bufferReader.ts +++ b/packages/typed-binary/src/io/bufferReader.ts @@ -13,59 +13,52 @@ export class BufferReader extends BufferIOBase implements ISerialInput { return this._cachedTextDecoder; } - private copyInputToHelper(bytes: number) { - for (let i = 0; i < bytes; ++i) { - this.helperByteView[this.switchEndianness ? bytes - 1 - i : i] = - this.uint8View[this.byteOffset++]; - } - } - readBool() { - return this.uint8View[this.byteOffset++] !== 0; + return this.dataView.getUint8(this.byteOffset++) !== 0; } readByte() { - return this.uint8View[this.byteOffset++]; + return this.dataView.getUint8(this.byteOffset++); } readFloat16() { - this.copyInputToHelper(2); - - return float16ToNumber(this.helperUint16View); + const value = this.dataView.getUint16(this.byteOffset, this.littleEndian); + this.byteOffset += 2; + return float16ToNumber(value); } readFloat32() { - this.copyInputToHelper(4); - - return this.helperFloat32View[0]; + const value = this.dataView.getFloat32(this.byteOffset, this.littleEndian); + this.byteOffset += 4; + return value; } readInt32() { - this.copyInputToHelper(4); - - return this.helperInt32View[0]; + const value = this.dataView.getInt32(this.byteOffset, this.littleEndian); + this.byteOffset += 4; + return value; } readUint32() { - this.copyInputToHelper(4); - - return this.helperUint32View[0]; + const value = this.dataView.getUint32(this.byteOffset, this.littleEndian); + this.byteOffset += 4; + return value; } readString() { // Looking for the 'NULL' byte. - let end = this.byteOffset; - while (end < this.uint8View.byteLength) { - if (this.uint8View[end++] === 0) { + let strLength = 0; + while (this.byteOffset + strLength < this.dataView.byteLength) { + if (this.dataView.getUint8(this.byteOffset + strLength++) === 0) { break; } } const result = this._textDecoder.decode( - this.uint8View.subarray(this.byteOffset, end - 1), + new Uint8Array(this.dataView.buffer, this.byteOffset, strLength - 1), ); - this.byteOffset = end; + this.byteOffset += strLength; return result; } @@ -82,7 +75,7 @@ export class BufferReader extends BufferIOBase implements ISerialInput { ); for (let i = 0; i < byteLength; ++i) { - destU8[i] = this.uint8View[this.byteOffset++]; + destU8[i] = this.dataView.getUint8(this.byteOffset++); } } } diff --git a/packages/typed-binary/src/io/bufferWriter.ts b/packages/typed-binary/src/io/bufferWriter.ts index f7cdd55..a5d1d56 100644 --- a/packages/typed-binary/src/io/bufferWriter.ts +++ b/packages/typed-binary/src/io/bufferWriter.ts @@ -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 & ArrayBufferView): void { @@ -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); } } } diff --git a/packages/typed-binary/src/io/float16converter.ts b/packages/typed-binary/src/io/float16converter.ts index c885433..d1a7ea5 100644 --- a/packages/typed-binary/src/io/float16converter.ts +++ b/packages/typed-binary/src/io/float16converter.ts @@ -1,9 +1,8 @@ -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); @@ -11,17 +10,13 @@ export function numberToFloat16(value: number): Uint16Array { 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(uint16Array: Uint16Array): number { - const float16 = uint16Array[0]; - const sign = (float16 & 0x8000) >> 15; - const exponent = (float16 & 0x7c00) >> 10; - const mantissa = float16 & 0x3ff; +export function float16ToNumber(uint16Encoding: number): number { + const sign = (uint16Encoding & 0x8000) >> 15; + const exponent = (uint16Encoding & 0x7c00) >> 10; + const mantissa = uint16Encoding & 0x3ff; if (exponent === 0) { return sign === 0 ? mantissa / 1024 : -mantissa / 1024; }