From 17981f4ab171ecdbe9bb7e08e7dbaeb899acd191 Mon Sep 17 00:00:00 2001 From: ayman Date: Thu, 22 Aug 2024 09:05:25 +0530 Subject: [PATCH 1/8] feat: add write int functions --- ts_src/browser.ts | 143 +++++++++++++++++++++++++++++++++++++++++++ ts_src/index.ts | 70 +++++++++++++++++++++ ts_src/tests.spec.ts | 140 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+) diff --git a/ts_src/browser.ts b/ts_src/browser.ts index b2bcad5..b5e23b8 100644 --- a/ts_src/browser.ts +++ b/ts_src/browser.ts @@ -306,3 +306,146 @@ export function readUInt64( return num; } } + +export function writeInt8( + buffer: Uint8Array, + value: number, + offset: number, +): number { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + if(value > 0x7f || value < -0x80) { + throw new RangeError(`The value of "value" is out of range. It must be >= -128 and <= 127. Received ${value}`); + } + + buffer[offset] = value; + return offset + 1; +} + +export function writeInt16( + buffer: Uint8Array, + value: number, + offset: number, + littleEndian: endian +): number { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + if(value > 0x7fff || value < -0x8000) { + throw new RangeError(`The value of "value" is out of range. It must be >= -32768 and <= 32767. Received ${value}`); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + } else { + buffer[offset] = (value >> 8) & 0xff; + buffer[offset + 1] = value & 0xff; + } + return offset + 2; +} + +export function writeInt32( + buffer: Uint8Array, + value: number, + offset: number, + littleEndian: endian +): number { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + buffer[offset + 2] = (value >> 16) & 0xff; + buffer[offset + 3] = (value >> 24) & 0xff; + } else { + buffer[offset] = (value >> 24) & 0xff; + buffer[offset + 1] = (value >> 16) & 0xff; + buffer[offset + 2] = (value >> 8) & 0xff; + buffer[offset + 3] = value & 0xff; + } + return offset + 4; +} + +export function writeInt64( + buffer: Uint8Array, + value: bigint, + offset: number, + littleEndian: endian +): number { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + buffer[offset] = Number(value & 0xffn); + buffer[offset + 1] = Number((value >> 8n) & 0xffn); + buffer[offset + 2] = Number((value >> 16n) & 0xffn); + buffer[offset + 3] = Number((value >> 24n) & 0xffn); + buffer[offset + 4] = Number((value >> 32n) & 0xffn); + buffer[offset + 5] = Number((value >> 40n) & 0xffn); + buffer[offset + 6] = Number((value >> 48n) & 0xffn); + buffer[offset + 7] = Number((value >> 56n) & 0xffn); + } else { + buffer[offset] = Number((value >> 56n) & 0xffn); + buffer[offset + 1] = Number((value >> 48n) & 0xffn); + buffer[offset + 2] = Number((value >> 40n) & 0xffn); + buffer[offset + 3] = Number((value >> 32n) & 0xffn); + buffer[offset + 4] = Number((value >> 24n) & 0xffn); + buffer[offset + 5] = Number((value >> 16n) & 0xffn); + buffer[offset + 6] = Number((value >> 8n) & 0xffn); + buffer[offset + 7] = Number(value & 0xffn); + } + + return offset + 8; +} + +export function readInt8( + buffer: Uint8Array, + offset: number +): number { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + const val = buffer[offset]; + + if (val <= 0x7f) { + return val; + }else { + return (val - 0x100); + } +} + +export function readInt16( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): number { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE" && buffer[offset + 1] <= 0x7f) { + return buffer[offset] + (buffer[offset + 1] << 8); + } else if(littleEndian === "LE" && buffer[offset + 1] > 0x7f) { + return buffer[offset] + (buffer[offset + 1] << 8) - 0x10000; + } else if (littleEndian === "BE" && buffer[offset] <= 0x7f) { + return (buffer[offset] << 8) + buffer[offset + 1]; + }else { + return (buffer[offset] << 8) + buffer[offset + 1] - 0x10000; + } +} \ No newline at end of file diff --git a/ts_src/index.ts b/ts_src/index.ts index d69ffbb..db8d898 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -187,3 +187,73 @@ export function readUInt64( return buf.readBigUInt64BE(offset); } } + +export function writeInt8( + buffer: Uint8Array, + value: number, + offset: number, +): number { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + if(value > 0x7f || value < -0x80) { + throw new RangeError(`The value of "value" is out of range. It must be >= -128 and <= 127. Received ${value}`); + } + + buffer[offset] = value; + return offset + 1; +} + +export function writeInt16( + buffer: Uint8Array, + value: number, + offset: number, + littleEndian: endian +): number { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + if(value > 0x7fff || value < -0x8000) { + throw new RangeError(`The value of "value" is out of range. It must be >= -32768 and <= 32767. Received ${value}`); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + } else { + buffer[offset] = (value >> 8) & 0xff; + buffer[offset + 1] = value & 0xff; + } + return offset + 2; +} + +export function readInt8(buffer: Uint8Array, offset: number): number { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + const buf = Buffer.from(buffer); + return buf.readInt8(offset); +} + +export function readInt16( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): number { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if(littleEndian === "LE") { + return Buffer.from(buffer).readInt16LE(offset); + }else { + return Buffer.from(buffer).readInt16BE(offset); + } +} \ No newline at end of file diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index d92aaf0..6aa5126 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -411,6 +411,146 @@ describe(`Uint8Array tools`, () => { ); } }); + + it("should be able to writeInt8", () => { + const arr = new Uint8Array(1); + const fixtures = [ + { + value: 1, + expect: Uint8Array.from([1]), + }, + { + value: 0x7f, + expect: Uint8Array.from([0x7f]), + }, + { + value: -0x80, + expect: Uint8Array.from([0x80]), + }, + { + value: -0x01, + expect: Uint8Array.from([0xff]), + } + ]; + + for (const fixture of fixtures) { + expect(tools.writeInt8(arr, fixture.value, 0)).toEqual(1); + expect(arr).toEqual(fixture.expect); + } + }); + + it("should be able to readInt8", () => { + const arr = new Uint8Array(1); + const fixtures = [ + { + value: 1, + expect: 1, + }, + { + value: 0x7f, + expect: 0x7f, + }, + { + value: -0x80, + expect: -0x80, + }, + { + value: -0x01, + expect: -0x01, + } + ]; + + for (const fixture of fixtures) { + tools.writeInt8(arr, fixture.value, 0); + expect(tools.readInt8(arr, 0)).toEqual(fixture.expect); + } + }) + + it("should be able to writeInt16 in little endian", () => { + const arr = new Uint8Array(2); + const fixtures = [ + { + value: 1, + expect: Uint8Array.from([1, 0]), + }, + { + value: 0x7fff, + expect: Uint8Array.from([0xff, 0x7f]), + }, + { + value: -0x8000, + expect: Uint8Array.from([0x00, 0x80]), + }, + { + value: -0x01, + expect: Uint8Array.from([0xff, 0xff]), + } + ]; + + for (const fixture of fixtures) { + expect(tools.writeInt16(arr, fixture.value, 0, "LE")).toEqual(2); + expect(arr).toEqual(fixture.expect); + } + }); + + it("should be able to writeInt16 in big endian", () => { + const arr = new Uint8Array(2); + const fixtures = [ + { + value: 1, + expect: Uint8Array.from([0, 1]), + }, + { + value: 0x7fff, + expect: Uint8Array.from([0x7f, 0xff]), + }, + { + value: -0x8000, + expect: Uint8Array.from([0x80, 0x00]), + }, + { + value: -0x01, + expect: Uint8Array.from([0xff, 0xff]), + } + ]; + + for (const fixture of fixtures) { + expect(tools.writeInt16(arr, fixture.value, 0, "BE")).toEqual(2); + expect(arr).toEqual(fixture.expect); + } + }); + + it("should be able to readInt16", () => { + const arr = new Uint8Array(2); + const fixtures = [ + { + value: 1, + expect: 1, + }, + { + value: 0x7fff, + expect: 0x7fff, + }, + { + value: -0x8000, + expect: -0x8000, + }, + { + value: -0x01, + expect: -0x01, + } + ]; + + for (const fixture of fixtures) { + tools.writeInt16(arr, fixture.value, 0, "LE"); + expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture.expect); + } + + for (const fixture of fixtures) { + tools.writeInt16(arr, fixture.value, 0, "BE"); + expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture.expect); + } + }); }); } }); From 43abaa1a7b641e5b8fa841a7303743e31e86c440 Mon Sep 17 00:00:00 2001 From: ayman Date: Fri, 23 Aug 2024 05:28:00 +0530 Subject: [PATCH 2/8] tests for writeInt and readInt --- ts_src/browser.ts | 105 ++++++++++++++----- ts_src/index.ts | 105 ++++++++++++++++--- ts_src/tests.spec.ts | 237 +++++++++++++++++++++++++++++++++---------- 3 files changed, 355 insertions(+), 92 deletions(-) diff --git a/ts_src/browser.ts b/ts_src/browser.ts index b5e23b8..c8bd4d4 100644 --- a/ts_src/browser.ts +++ b/ts_src/browser.ts @@ -310,17 +310,13 @@ export function readUInt64( export function writeInt8( buffer: Uint8Array, value: number, - offset: number, + offset: number ): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7f || value < -0x80) { - throw new RangeError(`The value of "value" is out of range. It must be >= -128 and <= 127. Received ${value}`); - } - - buffer[offset] = value; + buffer[offset] = value; return offset + 1; } @@ -334,10 +330,6 @@ export function writeInt16( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fff || value < -0x8000) { - throw new RangeError(`The value of "value" is out of range. It must be >= -32768 and <= 32767. Received ${value}`); - } - littleEndian = littleEndian.toUpperCase() as endian; if (littleEndian === "LE") { @@ -400,7 +392,7 @@ export function writeInt64( } else { buffer[offset] = Number((value >> 56n) & 0xffn); buffer[offset + 1] = Number((value >> 48n) & 0xffn); - buffer[offset + 2] = Number((value >> 40n) & 0xffn); + buffer[offset + 2] = Number((value >> 40n) & 0xffn); buffer[offset + 3] = Number((value >> 32n) & 0xffn); buffer[offset + 4] = Number((value >> 24n) & 0xffn); buffer[offset + 5] = Number((value >> 16n) & 0xffn); @@ -411,10 +403,7 @@ export function writeInt64( return offset + 8; } -export function readInt8( - buffer: Uint8Array, - offset: number -): number { +export function readInt8(buffer: Uint8Array, offset: number): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -423,8 +412,8 @@ export function readInt8( if (val <= 0x7f) { return val; - }else { - return (val - 0x100); + } else { + return val - 0x100; } } @@ -439,13 +428,77 @@ export function readInt16( littleEndian = littleEndian.toUpperCase() as endian; - if (littleEndian === "LE" && buffer[offset + 1] <= 0x7f) { - return buffer[offset] + (buffer[offset + 1] << 8); - } else if(littleEndian === "LE" && buffer[offset + 1] > 0x7f) { - return buffer[offset] + (buffer[offset + 1] << 8) - 0x10000; - } else if (littleEndian === "BE" && buffer[offset] <= 0x7f) { - return (buffer[offset] << 8) + buffer[offset + 1]; - }else { - return (buffer[offset] << 8) + buffer[offset + 1] - 0x10000; + if (littleEndian === "LE") { + const val = buffer[offset] + (buffer[offset + 1] << 8); + return buffer[offset + 1] <= 0x7f ? val : val - 0x10000; + } else { + const val = (buffer[offset] << 8) + buffer[offset + 1]; + return buffer[offset] <= 0x7f ? val : val - 0x10000; + } +} + +export function readInt32( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): number { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + const val = + buffer[offset] + + (buffer[offset + 1] << 8) + + (buffer[offset + 2] << 16) + + ((buffer[offset + 3] << 24) >>> 0); + return buffer[offset + 3] <= 0x7f ? val : val - 0x100000000; + } else { + const val = + ((buffer[offset] << 24) >>> 0) + + (buffer[offset + 1] << 16) + + (buffer[offset + 2] << 8) + + buffer[offset + 3]; + return buffer[offset] <= 0x7f ? val : val - 0x100000000; + } +} + +export function readInt64( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): bigint { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + let num = 0n; + if (littleEndian === "LE") { + num = (num << 8n) + BigInt(buffer[offset + 7]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset]); + + return buffer[offset + 7] <= 0x7f ? num : num - 0x10000000000000000n; + } else { + let num = 0n; + num = (num << 8n) + BigInt(buffer[offset]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 7]); + + return buffer[offset] <= 0x7f ? num : num - 0x10000000000000000n; } -} \ No newline at end of file +} diff --git a/ts_src/index.ts b/ts_src/index.ts index db8d898..1b26622 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -191,17 +191,16 @@ export function readUInt64( export function writeInt8( buffer: Uint8Array, value: number, - offset: number, + offset: number ): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7f || value < -0x80) { - throw new RangeError(`The value of "value" is out of range. It must be >= -128 and <= 127. Received ${value}`); - } + const buf = Buffer.alloc(1); + buf.writeInt8(value, 0); + buffer.set(Uint8Array.from(buf), offset); - buffer[offset] = value; return offset + 1; } @@ -215,20 +214,60 @@ export function writeInt16( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fff || value < -0x8000) { - throw new RangeError(`The value of "value" is out of range. It must be >= -32768 and <= 32767. Received ${value}`); + littleEndian = littleEndian.toUpperCase() as endian; + + const buf = Buffer.alloc(2); + if (littleEndian === "LE") { + buf.writeInt16LE(value, 0); + } else { + buf.writeInt16BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 2; +} + +export function writeInt32( + buffer: Uint8Array, + value: number, + offset: number, + littleEndian: endian +): number { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); } littleEndian = littleEndian.toUpperCase() as endian; + const buf = Buffer.alloc(4); if (littleEndian === "LE") { - buffer[offset] = value & 0xff; - buffer[offset + 1] = (value >> 8) & 0xff; + buf.writeInt32LE(value, 0); } else { - buffer[offset] = (value >> 8) & 0xff; - buffer[offset + 1] = value & 0xff; + buf.writeInt32BE(value, 0); } - return offset + 2; + buffer.set(Uint8Array.from(buf), offset); + return offset + 4; +} + +export function writeInt64( + buffer: Uint8Array, + value: bigint, + offset: number, + littleEndian: endian +): number { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + const buf = Buffer.alloc(8); + if (littleEndian === "LE") { + buf.writeBigInt64LE(value, 0); + } else { + buf.writeBigInt64BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 8; } export function readInt8(buffer: Uint8Array, offset: number): number { @@ -251,9 +290,45 @@ export function readInt16( littleEndian = littleEndian.toUpperCase() as endian; - if(littleEndian === "LE") { + if (littleEndian === "LE") { return Buffer.from(buffer).readInt16LE(offset); - }else { + } else { return Buffer.from(buffer).readInt16BE(offset); } -} \ No newline at end of file +} + +export function readInt32( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): number { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + return Buffer.from(buffer).readInt32LE(offset); + } else { + return Buffer.from(buffer).readInt32BE(offset); + } +} + +export function readInt64( + buffer: Uint8Array, + offset: number, + littleEndian: endian +): bigint { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + + littleEndian = littleEndian.toUpperCase() as endian; + + if (littleEndian === "LE") { + return Buffer.from(buffer).readBigInt64LE(offset); + } else { + return Buffer.from(buffer).readBigInt64BE(offset); + } +} diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index 6aa5126..e363b73 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -416,21 +416,21 @@ describe(`Uint8Array tools`, () => { const arr = new Uint8Array(1); const fixtures = [ { - value: 1, + value: 1, expect: Uint8Array.from([1]), }, { - value: 0x7f, + value: 0x7f, expect: Uint8Array.from([0x7f]), - }, + }, { value: -0x80, - expect: Uint8Array.from([0x80]), - }, + expect: Uint8Array.from([0x80]), + }, { - value: -0x01, + value: -0x01, expect: Uint8Array.from([0xff]), - } + }, ]; for (const fixture of fixtures) { @@ -443,112 +443,247 @@ describe(`Uint8Array tools`, () => { const arr = new Uint8Array(1); const fixtures = [ { - value: 1, + value: 1, expect: 1, }, { - value: 0x7f, + value: 0x7f, expect: 0x7f, - }, + }, { value: -0x80, - expect: -0x80, - }, + expect: -0x80, + }, { - value: -0x01, + value: -0x01, expect: -0x01, - } + }, ]; for (const fixture of fixtures) { tools.writeInt8(arr, fixture.value, 0); expect(tools.readInt8(arr, 0)).toEqual(fixture.expect); } - }) + }); - it("should be able to writeInt16 in little endian", () => { + it("should be able to writeInt16", () => { const arr = new Uint8Array(2); const fixtures = [ { - value: 1, + value: 1, expect: Uint8Array.from([1, 0]), }, { - value: 0x7fff, + value: 0x7fff, expect: Uint8Array.from([0xff, 0x7f]), - }, + }, { value: -0x8000, - expect: Uint8Array.from([0x00, 0x80]), - }, + expect: Uint8Array.from([0x00, 0x80]), + }, { - value: -0x01, + value: -0x01, expect: Uint8Array.from([0xff, 0xff]), - } + }, ]; for (const fixture of fixtures) { expect(tools.writeInt16(arr, fixture.value, 0, "LE")).toEqual(2); expect(arr).toEqual(fixture.expect); } + + for (const fixture of fixtures) { + expect(tools.writeInt16(arr, fixture.value, 0, "BE")).toEqual(2); + expect(arr).toEqual(fixture.expect.reverse()); + } }); - it("should be able to writeInt16 in big endian", () => { + it("should be able to readInt16", () => { const arr = new Uint8Array(2); const fixtures = [ { - value: 1, - expect: Uint8Array.from([0, 1]), + value: 1, + expect: 1, }, { - value: 0x7fff, - expect: Uint8Array.from([0x7f, 0xff]), - }, + value: 0x7fff, + expect: 0x7fff, + }, { value: -0x8000, - expect: Uint8Array.from([0x80, 0x00]), - }, + expect: -0x8000, + }, { - value: -0x01, - expect: Uint8Array.from([0xff, 0xff]), - } + value: -0x01, + expect: -0x01, + }, + ]; + + for (const fixture of fixtures) { + tools.writeInt16(arr, fixture.value, 0, "LE"); + expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture.expect); + } + + for (const fixture of fixtures) { + tools.writeInt16(arr, fixture.value, 0, "BE"); + expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture.expect); + } + }); + + it("should be able to writeInt32", () => { + const arr = new Uint8Array(4); + const fixtures = [ + { + value: 1, + expect: Uint8Array.from([1, 0, 0, 0]), + }, + { + value: 0x7fffffff, + expect: Uint8Array.from([0xff, 0xff, 0xff, 0x7f]), + }, + { + value: -0x80000000, + expect: Uint8Array.from([0x00, 0x00, 0x00, 0x80]), + }, + { + value: -0x01, + expect: Uint8Array.from([0xff, 0xff, 0xff, 0xff]), + }, ]; - + for (const fixture of fixtures) { - expect(tools.writeInt16(arr, fixture.value, 0, "BE")).toEqual(2); + expect(tools.writeInt32(arr, fixture.value, 0, "LE")).toEqual(4); expect(arr).toEqual(fixture.expect); } + + for (const fixture of fixtures) { + expect(tools.writeInt32(arr, fixture.value, 0, "BE")).toEqual(4); + expect(arr).toEqual(fixture.expect.reverse()); + } }); - it("should be able to readInt16", () => { - const arr = new Uint8Array(2); + it("should be able to readInt32", () => { + const arr = new Uint8Array(4); + const fixtures = [ { - value: 1, + value: 1, expect: 1, }, { - value: 0x7fff, - expect: 0x7fff, - }, + value: 0x7fffffff, + expect: 0x7fffffff, + }, { - value: -0x8000, - expect: -0x8000, - }, + value: -0x80000000, + expect: -0x80000000, + }, { - value: -0x01, + value: -0x01, expect: -0x01, - } + }, ]; for (const fixture of fixtures) { - tools.writeInt16(arr, fixture.value, 0, "LE"); - expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture.expect); + tools.writeInt32(arr, fixture.value, 0, "LE"); + expect(tools.readInt32(arr, 0, "LE")).toEqual(fixture.expect); } for (const fixture of fixtures) { - tools.writeInt16(arr, fixture.value, 0, "BE"); - expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture.expect); + tools.writeInt32(arr, fixture.value, 0, "BE"); + expect(tools.readInt32(arr, 0, "BE")).toEqual(fixture.expect); + } + }); + + it("should be able to writeInt64", () => { + const arr = new Uint8Array(8); + const fixtures = [ + { + value: 1n, + expect: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0]), + }, + { + value: 0x7fffffffffffffffn, + expect: Uint8Array.from([ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, + ]), + }, + { + value: -0x8000000000000000n, + expect: Uint8Array.from([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + ]), + }, + { + value: -0x01n, + expect: Uint8Array.from([ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + ]), + }, + ]; + + for (const fixture of fixtures) { + expect(tools.writeInt64(arr, fixture.value, 0, "LE")).toEqual(8); + expect(arr).toEqual(fixture.expect); + } + + for (const fixture of fixtures) { + expect(tools.writeInt64(arr, fixture.value, 0, "BE")).toEqual(8); + expect(arr).toEqual(fixture.expect.reverse()); + } + }); + + it("should be able to readInt64", () => { + const arr = new Uint8Array(8); + + const fixtures = [ + { + value: 1n, + expect: 1n, + }, + { + value: 0x7fffffffffffffffn, + expect: 0x7fffffffffffffffn, + }, + { + value: -0x8000000000000000n, + expect: -0x8000000000000000n, + }, + { + value: -0x01n, + expect: -0x01n, + }, + ]; + + for (const fixture of fixtures) { + tools.writeInt64(arr, fixture.value, 0, "LE"); + expect(tools.readInt64(arr, 0, "LE")).toEqual(fixture.expect); + } + + for (const fixture of fixtures) { + tools.writeInt64(arr, fixture.value, 0, "BE"); + expect(tools.readInt64(arr, 0, "BE")).toEqual(fixture.expect); + } + }); + + it("signed integer read-write functions should throw an error if the offset is out of bounds", () => { + const operation = ["read", "write"]; + const nums = [0, 1, 2, 3]; + + for (let i = 0; i < operation.length; i++) { + for (let j = 0; j < nums.length; j++) { + const fnName = + operation[i] + "Int" + ((1 << nums[j]) * 8).toString(); + const val = j === 4 ? 1n : 1; + for (const endian of ["BE", "LE"]) { + expect(() => + // @ts-ignore + tools[fnName](new Uint8Array(j + 1), val, j + 1, endian) + ).toThrowError( + new Error("Offset is outside the bounds of Uint8Array") + ); + } + } } }); }); From 6999116d916a15be3e38eae0386d07a62c331978 Mon Sep 17 00:00:00 2001 From: ayman Date: Wed, 28 Aug 2024 21:21:14 +0530 Subject: [PATCH 3/8] feat: throw errors if value is out of range --- src/cjs/browser.cjs | 158 ++++++++++++++++++++++++++++++++++++++++++- src/cjs/index.cjs | 111 +++++++++++++++++++++++++++++- src/cjs/index.d.ts | 16 +++-- src/mjs/browser.js | 148 ++++++++++++++++++++++++++++++++++++++++ src/mjs/index.js | 101 +++++++++++++++++++++++++++ ts_src/browser.ts | 44 +++++++++--- ts_src/index.ts | 30 +++++--- ts_src/tests.spec.ts | 56 +++++++++++---- 8 files changed, 626 insertions(+), 38 deletions(-) diff --git a/src/cjs/browser.cjs b/src/cjs/browser.cjs index 8c1facf..78011d9 100644 --- a/src/cjs/browser.cjs +++ b/src/cjs/browser.cjs @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0; +exports.readInt64 = exports.readInt32 = exports.readInt16 = exports.readInt8 = exports.writeInt64 = exports.writeInt32 = exports.writeInt16 = exports.writeInt8 = exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0; const HEX_STRINGS = "0123456789abcdefABCDEF"; const HEX_CODES = HEX_STRINGS.split("").map((c) => c.codePointAt(0)); const HEX_CODEPOINTS = Array(256) @@ -107,6 +107,7 @@ function writeUInt8(buffer, offset, value) { throw new Error(`The value of "value" is out of range. It must be >= 0 and <= ${0xff}. Received ${value}`); } buffer[offset] = value; + return offset + 1; } exports.writeUInt8 = writeUInt8; function writeUInt16(buffer, offset, value, littleEndian) { @@ -125,6 +126,7 @@ function writeUInt16(buffer, offset, value, littleEndian) { buffer[offset] = (value >> 8) & 0xff; buffer[offset + 1] = value & 0xff; } + return offset + 2; } exports.writeUInt16 = writeUInt16; function writeUInt32(buffer, offset, value, littleEndian) { @@ -147,6 +149,7 @@ function writeUInt32(buffer, offset, value, littleEndian) { buffer[offset + 2] = (value >> 8) & 0xff; buffer[offset + 3] = value & 0xff; } + return offset + 4; } exports.writeUInt32 = writeUInt32; function writeUInt64(buffer, offset, value, littleEndian) { @@ -177,6 +180,7 @@ function writeUInt64(buffer, offset, value, littleEndian) { buffer[offset + 6] = Number((value >> 8n) & 0xffn); buffer[offset + 7] = Number(value & 0xffn); } + return offset + 8; } exports.writeUInt64 = writeUInt64; function readUInt8(buffer, offset) { @@ -259,3 +263,155 @@ function readUInt64(buffer, offset, littleEndian) { } } exports.readUInt64 = readUInt64; +function writeInt8(buffer, offset, value) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + buffer[offset] = value; + return offset + 1; +} +exports.writeInt8 = writeInt8; +function writeInt16(buffer, offset, value, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + } + else { + buffer[offset] = (value >> 8) & 0xff; + buffer[offset + 1] = value & 0xff; + } + return offset + 2; +} +exports.writeInt16 = writeInt16; +function writeInt32(buffer, offset, value, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + buffer[offset + 2] = (value >> 16) & 0xff; + buffer[offset + 3] = (value >> 24) & 0xff; + } + else { + buffer[offset] = (value >> 24) & 0xff; + buffer[offset + 1] = (value >> 16) & 0xff; + buffer[offset + 2] = (value >> 8) & 0xff; + buffer[offset + 3] = value & 0xff; + } + return offset + 4; +} +exports.writeInt32 = writeInt32; +function writeInt64(buffer, offset, value, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = Number(value & 0xffn); + buffer[offset + 1] = Number((value >> 8n) & 0xffn); + buffer[offset + 2] = Number((value >> 16n) & 0xffn); + buffer[offset + 3] = Number((value >> 24n) & 0xffn); + buffer[offset + 4] = Number((value >> 32n) & 0xffn); + buffer[offset + 5] = Number((value >> 40n) & 0xffn); + buffer[offset + 6] = Number((value >> 48n) & 0xffn); + buffer[offset + 7] = Number((value >> 56n) & 0xffn); + } + else { + buffer[offset] = Number((value >> 56n) & 0xffn); + buffer[offset + 1] = Number((value >> 48n) & 0xffn); + buffer[offset + 2] = Number((value >> 40n) & 0xffn); + buffer[offset + 3] = Number((value >> 32n) & 0xffn); + buffer[offset + 4] = Number((value >> 24n) & 0xffn); + buffer[offset + 5] = Number((value >> 16n) & 0xffn); + buffer[offset + 6] = Number((value >> 8n) & 0xffn); + buffer[offset + 7] = Number(value & 0xffn); + } + return offset + 8; +} +exports.writeInt64 = writeInt64; +function readInt8(buffer, offset) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const val = buffer[offset]; + if (val <= 0x7f) { + return val; + } + else { + return val - 0x100; + } +} +exports.readInt8 = readInt8; +function readInt16(buffer, offset, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + const val = buffer[offset] + (buffer[offset + 1] << 8); + return buffer[offset + 1] <= 0x7f ? val : val - 0x10000; + } + else { + const val = (buffer[offset] << 8) + buffer[offset + 1]; + return buffer[offset] <= 0x7f ? val : val - 0x10000; + } +} +exports.readInt16 = readInt16; +function readInt32(buffer, offset, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + const val = buffer[offset] + + (buffer[offset + 1] << 8) + + (buffer[offset + 2] << 16) + + ((buffer[offset + 3] << 24) >>> 0); + return buffer[offset + 3] <= 0x7f ? val : val - 0x100000000; + } + else { + const val = ((buffer[offset] << 24) >>> 0) + + (buffer[offset + 1] << 16) + + (buffer[offset + 2] << 8) + + buffer[offset + 3]; + return buffer[offset] <= 0x7f ? val : val - 0x100000000; + } +} +exports.readInt32 = readInt32; +function readInt64(buffer, offset, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + let num = 0n; + if (littleEndian === "LE") { + num = (num << 8n) + BigInt(buffer[offset + 7]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset]); + return buffer[offset + 7] <= 0x7f ? num : num - 0x10000000000000000n; + } + else { + let num = 0n; + num = (num << 8n) + BigInt(buffer[offset]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 7]); + return buffer[offset] <= 0x7f ? num : num - 0x10000000000000000n; + } +} +exports.readInt64 = readInt64; diff --git a/src/cjs/index.cjs b/src/cjs/index.cjs index 8665c71..054e4f1 100644 --- a/src/cjs/index.cjs +++ b/src/cjs/index.cjs @@ -1,6 +1,6 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0; +exports.readInt64 = exports.readInt32 = exports.readInt16 = exports.readInt8 = exports.writeInt64 = exports.writeInt32 = exports.writeInt16 = exports.writeInt8 = exports.readUInt64 = exports.readUInt32 = exports.readUInt16 = exports.readUInt8 = exports.writeUInt64 = exports.writeUInt32 = exports.writeUInt16 = exports.writeUInt8 = exports.compare = exports.fromBase64 = exports.toBase64 = exports.fromHex = exports.toHex = exports.concat = exports.fromUtf8 = exports.toUtf8 = void 0; function toUtf8(bytes) { return Buffer.from(bytes || []).toString(); } @@ -40,6 +40,7 @@ function writeUInt8(buffer, offset, value) { const buf = Buffer.alloc(1); buf.writeUInt8(value, 0); buffer.set(Uint8Array.from(buf), offset); + return offset + 1; } exports.writeUInt8 = writeUInt8; function writeUInt16(buffer, offset, value, littleEndian) { @@ -55,6 +56,7 @@ function writeUInt16(buffer, offset, value, littleEndian) { buf.writeUInt16BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 2; } exports.writeUInt16 = writeUInt16; function writeUInt32(buffer, offset, value, littleEndian) { @@ -70,6 +72,7 @@ function writeUInt32(buffer, offset, value, littleEndian) { buf.writeUInt32BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 4; } exports.writeUInt32 = writeUInt32; function writeUInt64(buffer, offset, value, littleEndian) { @@ -88,6 +91,7 @@ function writeUInt64(buffer, offset, value, littleEndian) { buf.writeBigUInt64BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 8; } exports.writeUInt64 = writeUInt64; function readUInt8(buffer, offset) { @@ -140,3 +144,108 @@ function readUInt64(buffer, offset, littleEndian) { } } exports.readUInt64 = readUInt64; +function writeInt8(buffer, offset, value) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const buf = Buffer.alloc(1); + buf.writeInt8(value, 0); + buffer.set(Uint8Array.from(buf), offset); + return offset + 1; +} +exports.writeInt8 = writeInt8; +function writeInt16(buffer, offset, value, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(2); + if (littleEndian === "LE") { + buf.writeInt16LE(value, 0); + } + else { + buf.writeInt16BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 2; +} +exports.writeInt16 = writeInt16; +function writeInt32(buffer, offset, value, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(4); + if (littleEndian === "LE") { + buf.writeInt32LE(value, 0); + } + else { + buf.writeInt32BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 4; +} +exports.writeInt32 = writeInt32; +function writeInt64(buffer, offset, value, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(8); + if (littleEndian === "LE") { + buf.writeBigInt64LE(value, 0); + } + else { + buf.writeBigInt64BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 8; +} +exports.writeInt64 = writeInt64; +function readInt8(buffer, offset) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const buf = Buffer.from(buffer); + return buf.readInt8(offset); +} +exports.readInt8 = readInt8; +function readInt16(buffer, offset, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readInt16LE(offset); + } + else { + return Buffer.from(buffer).readInt16BE(offset); + } +} +exports.readInt16 = readInt16; +function readInt32(buffer, offset, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readInt32LE(offset); + } + else { + return Buffer.from(buffer).readInt32BE(offset); + } +} +exports.readInt32 = readInt32; +function readInt64(buffer, offset, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readBigInt64LE(offset); + } + else { + return Buffer.from(buffer).readBigInt64BE(offset); + } +} +exports.readInt64 = readInt64; diff --git a/src/cjs/index.d.ts b/src/cjs/index.d.ts index 5cbe104..14ae044 100644 --- a/src/cjs/index.d.ts +++ b/src/cjs/index.d.ts @@ -8,11 +8,19 @@ export declare function fromBase64(base64: string): Uint8Array; export declare type CompareResult = -1 | 0 | 1; export declare function compare(v1: Uint8Array, v2: Uint8Array): CompareResult; export declare type endian = "LE" | "BE" | "le" | "be"; -export declare function writeUInt8(buffer: Uint8Array, offset: number, value: number): void; -export declare function writeUInt16(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): void; -export declare function writeUInt32(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): void; -export declare function writeUInt64(buffer: Uint8Array, offset: number, value: bigint, littleEndian: endian): void; +export declare function writeUInt8(buffer: Uint8Array, offset: number, value: number): number; +export declare function writeUInt16(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): number; +export declare function writeUInt32(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): number; +export declare function writeUInt64(buffer: Uint8Array, offset: number, value: bigint, littleEndian: endian): number; export declare function readUInt8(buffer: Uint8Array, offset: number): number; export declare function readUInt16(buffer: Uint8Array, offset: number, littleEndian: endian): number; export declare function readUInt32(buffer: Uint8Array, offset: number, littleEndian: endian): number; export declare function readUInt64(buffer: Uint8Array, offset: number, littleEndian: endian): bigint; +export declare function writeInt8(buffer: Uint8Array, offset: number, value: number): number; +export declare function writeInt16(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): number; +export declare function writeInt32(buffer: Uint8Array, offset: number, value: number, littleEndian: endian): number; +export declare function writeInt64(buffer: Uint8Array, offset: number, value: bigint, littleEndian: endian): number; +export declare function readInt8(buffer: Uint8Array, offset: number): number; +export declare function readInt16(buffer: Uint8Array, offset: number, littleEndian: endian): number; +export declare function readInt32(buffer: Uint8Array, offset: number, littleEndian: endian): number; +export declare function readInt64(buffer: Uint8Array, offset: number, littleEndian: endian): bigint; diff --git a/src/mjs/browser.js b/src/mjs/browser.js index aaab7e4..a28c675 100644 --- a/src/mjs/browser.js +++ b/src/mjs/browser.js @@ -96,6 +96,7 @@ export function writeUInt8(buffer, offset, value) { throw new Error(`The value of "value" is out of range. It must be >= 0 and <= ${0xff}. Received ${value}`); } buffer[offset] = value; + return offset + 1; } export function writeUInt16(buffer, offset, value, littleEndian) { if (offset + 2 > buffer.length) { @@ -113,6 +114,7 @@ export function writeUInt16(buffer, offset, value, littleEndian) { buffer[offset] = (value >> 8) & 0xff; buffer[offset + 1] = value & 0xff; } + return offset + 2; } export function writeUInt32(buffer, offset, value, littleEndian) { if (offset + 4 > buffer.length) { @@ -134,6 +136,7 @@ export function writeUInt32(buffer, offset, value, littleEndian) { buffer[offset + 2] = (value >> 8) & 0xff; buffer[offset + 3] = value & 0xff; } + return offset + 4; } export function writeUInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { @@ -163,6 +166,7 @@ export function writeUInt64(buffer, offset, value, littleEndian) { buffer[offset + 6] = Number((value >> 8n) & 0xffn); buffer[offset + 7] = Number(value & 0xffn); } + return offset + 8; } export function readUInt8(buffer, offset) { if (offset + 1 > buffer.length) { @@ -240,3 +244,147 @@ export function readUInt64(buffer, offset, littleEndian) { return num; } } +export function writeInt8(buffer, offset, value) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + buffer[offset] = value; + return offset + 1; +} +export function writeInt16(buffer, offset, value, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + } + else { + buffer[offset] = (value >> 8) & 0xff; + buffer[offset + 1] = value & 0xff; + } + return offset + 2; +} +export function writeInt32(buffer, offset, value, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = value & 0xff; + buffer[offset + 1] = (value >> 8) & 0xff; + buffer[offset + 2] = (value >> 16) & 0xff; + buffer[offset + 3] = (value >> 24) & 0xff; + } + else { + buffer[offset] = (value >> 24) & 0xff; + buffer[offset + 1] = (value >> 16) & 0xff; + buffer[offset + 2] = (value >> 8) & 0xff; + buffer[offset + 3] = value & 0xff; + } + return offset + 4; +} +export function writeInt64(buffer, offset, value, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + buffer[offset] = Number(value & 0xffn); + buffer[offset + 1] = Number((value >> 8n) & 0xffn); + buffer[offset + 2] = Number((value >> 16n) & 0xffn); + buffer[offset + 3] = Number((value >> 24n) & 0xffn); + buffer[offset + 4] = Number((value >> 32n) & 0xffn); + buffer[offset + 5] = Number((value >> 40n) & 0xffn); + buffer[offset + 6] = Number((value >> 48n) & 0xffn); + buffer[offset + 7] = Number((value >> 56n) & 0xffn); + } + else { + buffer[offset] = Number((value >> 56n) & 0xffn); + buffer[offset + 1] = Number((value >> 48n) & 0xffn); + buffer[offset + 2] = Number((value >> 40n) & 0xffn); + buffer[offset + 3] = Number((value >> 32n) & 0xffn); + buffer[offset + 4] = Number((value >> 24n) & 0xffn); + buffer[offset + 5] = Number((value >> 16n) & 0xffn); + buffer[offset + 6] = Number((value >> 8n) & 0xffn); + buffer[offset + 7] = Number(value & 0xffn); + } + return offset + 8; +} +export function readInt8(buffer, offset) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const val = buffer[offset]; + if (val <= 0x7f) { + return val; + } + else { + return val - 0x100; + } +} +export function readInt16(buffer, offset, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + const val = buffer[offset] + (buffer[offset + 1] << 8); + return buffer[offset + 1] <= 0x7f ? val : val - 0x10000; + } + else { + const val = (buffer[offset] << 8) + buffer[offset + 1]; + return buffer[offset] <= 0x7f ? val : val - 0x10000; + } +} +export function readInt32(buffer, offset, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + const val = buffer[offset] + + (buffer[offset + 1] << 8) + + (buffer[offset + 2] << 16) + + ((buffer[offset + 3] << 24) >>> 0); + return buffer[offset + 3] <= 0x7f ? val : val - 0x100000000; + } + else { + const val = ((buffer[offset] << 24) >>> 0) + + (buffer[offset + 1] << 16) + + (buffer[offset + 2] << 8) + + buffer[offset + 3]; + return buffer[offset] <= 0x7f ? val : val - 0x100000000; + } +} +export function readInt64(buffer, offset, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + let num = 0n; + if (littleEndian === "LE") { + num = (num << 8n) + BigInt(buffer[offset + 7]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset]); + return buffer[offset + 7] <= 0x7f ? num : num - 0x10000000000000000n; + } + else { + let num = 0n; + num = (num << 8n) + BigInt(buffer[offset]); + num = (num << 8n) + BigInt(buffer[offset + 1]); + num = (num << 8n) + BigInt(buffer[offset + 2]); + num = (num << 8n) + BigInt(buffer[offset + 3]); + num = (num << 8n) + BigInt(buffer[offset + 4]); + num = (num << 8n) + BigInt(buffer[offset + 5]); + num = (num << 8n) + BigInt(buffer[offset + 6]); + num = (num << 8n) + BigInt(buffer[offset + 7]); + return buffer[offset] <= 0x7f ? num : num - 0x10000000000000000n; + } +} diff --git a/src/mjs/index.js b/src/mjs/index.js index 8e41336..143665f 100644 --- a/src/mjs/index.js +++ b/src/mjs/index.js @@ -29,6 +29,7 @@ export function writeUInt8(buffer, offset, value) { const buf = Buffer.alloc(1); buf.writeUInt8(value, 0); buffer.set(Uint8Array.from(buf), offset); + return offset + 1; } export function writeUInt16(buffer, offset, value, littleEndian) { if (offset + 2 > buffer.length) { @@ -43,6 +44,7 @@ export function writeUInt16(buffer, offset, value, littleEndian) { buf.writeUInt16BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 2; } export function writeUInt32(buffer, offset, value, littleEndian) { if (offset + 4 > buffer.length) { @@ -57,6 +59,7 @@ export function writeUInt32(buffer, offset, value, littleEndian) { buf.writeUInt32BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 4; } export function writeUInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { @@ -74,6 +77,7 @@ export function writeUInt64(buffer, offset, value, littleEndian) { buf.writeBigUInt64BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + return offset + 8; } export function readUInt8(buffer, offset) { if (offset + 1 > buffer.length) { @@ -121,3 +125,100 @@ export function readUInt64(buffer, offset, littleEndian) { return buf.readBigUInt64BE(offset); } } +export function writeInt8(buffer, offset, value) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const buf = Buffer.alloc(1); + buf.writeInt8(value, 0); + buffer.set(Uint8Array.from(buf), offset); + return offset + 1; +} +export function writeInt16(buffer, offset, value, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(2); + if (littleEndian === "LE") { + buf.writeInt16LE(value, 0); + } + else { + buf.writeInt16BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 2; +} +export function writeInt32(buffer, offset, value, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(4); + if (littleEndian === "LE") { + buf.writeInt32LE(value, 0); + } + else { + buf.writeInt32BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 4; +} +export function writeInt64(buffer, offset, value, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + const buf = Buffer.alloc(8); + if (littleEndian === "LE") { + buf.writeBigInt64LE(value, 0); + } + else { + buf.writeBigInt64BE(value, 0); + } + buffer.set(Uint8Array.from(buf), offset); + return offset + 8; +} +export function readInt8(buffer, offset) { + if (offset + 1 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + const buf = Buffer.from(buffer); + return buf.readInt8(offset); +} +export function readInt16(buffer, offset, littleEndian) { + if (offset + 2 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readInt16LE(offset); + } + else { + return Buffer.from(buffer).readInt16BE(offset); + } +} +export function readInt32(buffer, offset, littleEndian) { + if (offset + 4 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readInt32LE(offset); + } + else { + return Buffer.from(buffer).readInt32BE(offset); + } +} +export function readInt64(buffer, offset, littleEndian) { + if (offset + 8 > buffer.length) { + throw new Error("Offset is outside the bounds of Uint8Array"); + } + littleEndian = littleEndian.toUpperCase(); + if (littleEndian === "LE") { + return Buffer.from(buffer).readBigInt64LE(offset); + } + else { + return Buffer.from(buffer).readBigInt64BE(offset); + } +} diff --git a/ts_src/browser.ts b/ts_src/browser.ts index c8bd4d4..c078510 100644 --- a/ts_src/browser.ts +++ b/ts_src/browser.ts @@ -104,7 +104,7 @@ export function writeUInt8( buffer: Uint8Array, offset: number, value: number -): void { +): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -116,6 +116,8 @@ export function writeUInt8( } buffer[offset] = value; + + return offset + 1; } export function writeUInt16( @@ -123,7 +125,7 @@ export function writeUInt16( offset: number, value: number, littleEndian: endian -): void { +): number { if (offset + 2 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -141,6 +143,8 @@ export function writeUInt16( buffer[offset] = (value >> 8) & 0xff; buffer[offset + 1] = value & 0xff; } + + return offset + 2; } export function writeUInt32( @@ -148,7 +152,7 @@ export function writeUInt32( offset: number, value: number, littleEndian: endian -): void { +): number { if (offset + 4 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -172,6 +176,8 @@ export function writeUInt32( buffer[offset + 2] = (value >> 8) & 0xff; buffer[offset + 3] = value & 0xff; } + + return offset + 4; } export function writeUInt64( @@ -179,7 +185,7 @@ export function writeUInt64( offset: number, value: bigint, littleEndian: endian -): void { +): number { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -210,6 +216,8 @@ export function writeUInt64( buffer[offset + 6] = Number((value >> 8n) & 0xffn); buffer[offset + 7] = Number(value & 0xffn); } + + return offset + 8; } export function readUInt8(buffer: Uint8Array, offset: number): number { @@ -309,27 +317,35 @@ export function readUInt64( export function writeInt8( buffer: Uint8Array, - value: number, - offset: number + offset: number, + value: number ): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if(value > 0x7f || value < -0x80) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80} and <= ${0x7f}. Received ${value}`); + } + buffer[offset] = value; return offset + 1; } export function writeInt16( buffer: Uint8Array, - value: number, offset: number, + value: number, littleEndian: endian ): number { if (offset + 2 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if(value > 0x7fff || value < -0x8000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000} and <= ${0x7fff}. Received ${value}`); + } + littleEndian = littleEndian.toUpperCase() as endian; if (littleEndian === "LE") { @@ -344,14 +360,18 @@ export function writeInt16( export function writeInt32( buffer: Uint8Array, - value: number, offset: number, + value: number, littleEndian: endian ): number { if (offset + 4 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if(value > 0x7fffffff || value < -0x80000000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80000000} and <= ${0x7fffffff}. Received ${value}`); + } + littleEndian = littleEndian.toUpperCase() as endian; if (littleEndian === "LE") { @@ -370,14 +390,18 @@ export function writeInt32( export function writeInt64( buffer: Uint8Array, - value: bigint, offset: number, + value: bigint, littleEndian: endian ): number { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if(value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } + littleEndian = littleEndian.toUpperCase() as endian; if (littleEndian === "LE") { @@ -408,6 +432,8 @@ export function readInt8(buffer: Uint8Array, offset: number): number { throw new Error("Offset is outside the bounds of Uint8Array"); } + + const val = buffer[offset]; if (val <= 0x7f) { diff --git a/ts_src/index.ts b/ts_src/index.ts index 1b26622..58d8eac 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -37,7 +37,7 @@ export function writeUInt8( buffer: Uint8Array, offset: number, value: number -): void { +): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -45,6 +45,8 @@ export function writeUInt8( const buf = Buffer.alloc(1); buf.writeUInt8(value, 0); buffer.set(Uint8Array.from(buf), offset); + + return offset + 1; } export function writeUInt16( @@ -52,7 +54,7 @@ export function writeUInt16( offset: number, value: number, littleEndian: endian -): void { +): number { if (offset + 2 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -67,6 +69,8 @@ export function writeUInt16( buf.writeUInt16BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + + return offset + 2; } export function writeUInt32( @@ -74,7 +78,7 @@ export function writeUInt32( offset: number, value: number, littleEndian: endian -): void { +): number { if (offset + 4 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -89,6 +93,8 @@ export function writeUInt32( buf.writeUInt32BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + + return offset + 4; } export function writeUInt64( @@ -96,7 +102,7 @@ export function writeUInt64( offset: number, value: bigint, littleEndian: endian -): void { +): number { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } @@ -117,6 +123,8 @@ export function writeUInt64( buf.writeBigUInt64BE(value, 0); } buffer.set(Uint8Array.from(buf), offset); + + return offset + 8; } export function readUInt8(buffer: Uint8Array, offset: number): number { @@ -190,8 +198,8 @@ export function readUInt64( export function writeInt8( buffer: Uint8Array, - value: number, - offset: number + offset: number, + value: number ): number { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); @@ -206,8 +214,8 @@ export function writeInt8( export function writeInt16( buffer: Uint8Array, - value: number, offset: number, + value: number, littleEndian: endian ): number { if (offset + 2 > buffer.length) { @@ -228,8 +236,8 @@ export function writeInt16( export function writeInt32( buffer: Uint8Array, - value: number, offset: number, + value: number, littleEndian: endian ): number { if (offset + 4 > buffer.length) { @@ -250,14 +258,18 @@ export function writeInt32( export function writeInt64( buffer: Uint8Array, - value: bigint, offset: number, + value: bigint, littleEndian: endian ): number { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if(value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } + littleEndian = littleEndian.toUpperCase() as endian; const buf = Buffer.alloc(8); diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index e363b73..4efbb87 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -434,7 +434,7 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - expect(tools.writeInt8(arr, fixture.value, 0)).toEqual(1); + expect(tools.writeInt8(arr, 0, fixture.value)).toEqual(1); expect(arr).toEqual(fixture.expect); } }); @@ -461,7 +461,7 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - tools.writeInt8(arr, fixture.value, 0); + tools.writeInt8(arr, 0, fixture.value); expect(tools.readInt8(arr, 0)).toEqual(fixture.expect); } }); @@ -488,12 +488,12 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - expect(tools.writeInt16(arr, fixture.value, 0, "LE")).toEqual(2); + expect(tools.writeInt16(arr, 0, fixture.value, "LE")).toEqual(2); expect(arr).toEqual(fixture.expect); } for (const fixture of fixtures) { - expect(tools.writeInt16(arr, fixture.value, 0, "BE")).toEqual(2); + expect(tools.writeInt16(arr, 0, fixture.value, "BE")).toEqual(2); expect(arr).toEqual(fixture.expect.reverse()); } }); @@ -520,12 +520,12 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - tools.writeInt16(arr, fixture.value, 0, "LE"); + tools.writeInt16(arr, 0, fixture.value, "LE"); expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture.expect); } for (const fixture of fixtures) { - tools.writeInt16(arr, fixture.value, 0, "BE"); + tools.writeInt16(arr, 0, fixture.value, "BE"); expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture.expect); } }); @@ -552,12 +552,12 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - expect(tools.writeInt32(arr, fixture.value, 0, "LE")).toEqual(4); + expect(tools.writeInt32(arr, 0, fixture.value, "LE")).toEqual(4); expect(arr).toEqual(fixture.expect); } for (const fixture of fixtures) { - expect(tools.writeInt32(arr, fixture.value, 0, "BE")).toEqual(4); + expect(tools.writeInt32(arr, 0, fixture.value, "BE")).toEqual(4); expect(arr).toEqual(fixture.expect.reverse()); } }); @@ -585,12 +585,12 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - tools.writeInt32(arr, fixture.value, 0, "LE"); + tools.writeInt32(arr, 0, fixture.value, "LE"); expect(tools.readInt32(arr, 0, "LE")).toEqual(fixture.expect); } for (const fixture of fixtures) { - tools.writeInt32(arr, fixture.value, 0, "BE"); + tools.writeInt32(arr, 0, fixture.value, "BE"); expect(tools.readInt32(arr, 0, "BE")).toEqual(fixture.expect); } }); @@ -623,12 +623,12 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - expect(tools.writeInt64(arr, fixture.value, 0, "LE")).toEqual(8); + expect(tools.writeInt64(arr, 0, fixture.value, "LE")).toEqual(8); expect(arr).toEqual(fixture.expect); } for (const fixture of fixtures) { - expect(tools.writeInt64(arr, fixture.value, 0, "BE")).toEqual(8); + expect(tools.writeInt64(arr, 0, fixture.value, "BE")).toEqual(8); expect(arr).toEqual(fixture.expect.reverse()); } }); @@ -656,16 +656,44 @@ describe(`Uint8Array tools`, () => { ]; for (const fixture of fixtures) { - tools.writeInt64(arr, fixture.value, 0, "LE"); + tools.writeInt64(arr, 0, fixture.value, "LE"); expect(tools.readInt64(arr, 0, "LE")).toEqual(fixture.expect); } for (const fixture of fixtures) { - tools.writeInt64(arr, fixture.value, 0, "BE"); + tools.writeInt64(arr, 0, fixture.value, "BE"); expect(tools.readInt64(arr, 0, "BE")).toEqual(fixture.expect); } }); + it("signed integer functions should throw if the value is out of range", () => { + const nums = [0, 1, 2, 3]; + + for(let i = 0; i < nums.length; i++) { + const bitLength = (1 << nums[i]) * 8; + const fnName = "writeInt" + (bitLength).toString(); + const rawLow = BigInt(-(2n ** BigInt(bitLength - 1))); + const rawHigh = -rawLow - 1n; + const rawHighValue = rawHigh + 1n; + const rawLowValue = rawLow - 1n; + + const low = i === 3 ? rawLow : Number(rawLow); + const high = i === 3 ? rawHigh : Number(rawHigh); + const values = [i === 3 ? rawLowValue : Number(rawLowValue), i === 3 ? rawHighValue : Number(rawHighValue)]; + + for (const value of values) { + for(const endian of ["BE", "LE"]) { + expect(() => + //@ts-ignore + tools[fnName](new Uint8Array(bitLength / 8 + 1), 0, value, endian) + ).toThrowError( + new Error(`The value of "value" is out of range. It must be >= ${low} and <= ${high}. Received ${value}`) + ); + } + } + } + }); + it("signed integer read-write functions should throw an error if the offset is out of bounds", () => { const operation = ["read", "write"]; const nums = [0, 1, 2, 3]; From 2f8fbf9ee687e835d58bc792df8bfaf6132b5ba4 Mon Sep 17 00:00:00 2001 From: ayman Date: Wed, 28 Aug 2024 21:26:03 +0530 Subject: [PATCH 4/8] chore: add new build --- src/cjs/browser.cjs | 12 ++++++++++++ src/cjs/index.cjs | 3 +++ src/mjs/browser.js | 12 ++++++++++++ src/mjs/index.js | 3 +++ 4 files changed, 30 insertions(+) diff --git a/src/cjs/browser.cjs b/src/cjs/browser.cjs index 78011d9..5893dbf 100644 --- a/src/cjs/browser.cjs +++ b/src/cjs/browser.cjs @@ -267,6 +267,9 @@ function writeInt8(buffer, offset, value) { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7f || value < -0x80) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80} and <= ${0x7f}. Received ${value}`); + } buffer[offset] = value; return offset + 1; } @@ -275,6 +278,9 @@ function writeInt16(buffer, offset, value, littleEndian) { if (offset + 2 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fff || value < -0x8000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000} and <= ${0x7fff}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = value & 0xff; @@ -291,6 +297,9 @@ function writeInt32(buffer, offset, value, littleEndian) { if (offset + 4 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffff || value < -0x80000000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80000000} and <= ${0x7fffffff}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = value & 0xff; @@ -311,6 +320,9 @@ function writeInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = Number(value & 0xffn); diff --git a/src/cjs/index.cjs b/src/cjs/index.cjs index 054e4f1..ba01ad8 100644 --- a/src/cjs/index.cjs +++ b/src/cjs/index.cjs @@ -190,6 +190,9 @@ function writeInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); const buf = Buffer.alloc(8); if (littleEndian === "LE") { diff --git a/src/mjs/browser.js b/src/mjs/browser.js index a28c675..7d815c1 100644 --- a/src/mjs/browser.js +++ b/src/mjs/browser.js @@ -248,6 +248,9 @@ export function writeInt8(buffer, offset, value) { if (offset + 1 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7f || value < -0x80) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80} and <= ${0x7f}. Received ${value}`); + } buffer[offset] = value; return offset + 1; } @@ -255,6 +258,9 @@ export function writeInt16(buffer, offset, value, littleEndian) { if (offset + 2 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fff || value < -0x8000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000} and <= ${0x7fff}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = value & 0xff; @@ -270,6 +276,9 @@ export function writeInt32(buffer, offset, value, littleEndian) { if (offset + 4 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffff || value < -0x80000000) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x80000000} and <= ${0x7fffffff}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = value & 0xff; @@ -289,6 +298,9 @@ export function writeInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); if (littleEndian === "LE") { buffer[offset] = Number(value & 0xffn); diff --git a/src/mjs/index.js b/src/mjs/index.js index 143665f..3e3a85b 100644 --- a/src/mjs/index.js +++ b/src/mjs/index.js @@ -168,6 +168,9 @@ export function writeInt64(buffer, offset, value, littleEndian) { if (offset + 8 > buffer.length) { throw new Error("Offset is outside the bounds of Uint8Array"); } + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + } littleEndian = littleEndian.toUpperCase(); const buf = Buffer.alloc(8); if (littleEndian === "LE") { From 8047662ddd70efbf04ce640b0da9ce5228396c01 Mon Sep 17 00:00:00 2001 From: ayman Date: Wed, 28 Aug 2024 21:31:13 +0530 Subject: [PATCH 5/8] chore: remove ts-ignore comments --- ts_src/browser.ts | 26 ++++++++++++++++---------- ts_src/index.ts | 6 ++++-- ts_src/tests.spec.ts | 28 ++++++++++++++++++---------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/ts_src/browser.ts b/ts_src/browser.ts index c078510..d91f6e7 100644 --- a/ts_src/browser.ts +++ b/ts_src/browser.ts @@ -324,8 +324,10 @@ export function writeInt8( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7f || value < -0x80) { - throw new Error(`The value of "value" is out of range. It must be >= ${-0x80} and <= ${0x7f}. Received ${value}`); + if (value > 0x7f || value < -0x80) { + throw new Error( + `The value of "value" is out of range. It must be >= ${-0x80} and <= ${0x7f}. Received ${value}` + ); } buffer[offset] = value; @@ -342,8 +344,10 @@ export function writeInt16( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fff || value < -0x8000) { - throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000} and <= ${0x7fff}. Received ${value}`); + if (value > 0x7fff || value < -0x8000) { + throw new Error( + `The value of "value" is out of range. It must be >= ${-0x8000} and <= ${0x7fff}. Received ${value}` + ); } littleEndian = littleEndian.toUpperCase() as endian; @@ -368,8 +372,10 @@ export function writeInt32( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fffffff || value < -0x80000000) { - throw new Error(`The value of "value" is out of range. It must be >= ${-0x80000000} and <= ${0x7fffffff}. Received ${value}`); + if (value > 0x7fffffff || value < -0x80000000) { + throw new Error( + `The value of "value" is out of range. It must be >= ${-0x80000000} and <= ${0x7fffffff}. Received ${value}` + ); } littleEndian = littleEndian.toUpperCase() as endian; @@ -398,8 +404,10 @@ export function writeInt64( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { - throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error( + `The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}` + ); } littleEndian = littleEndian.toUpperCase() as endian; @@ -432,8 +440,6 @@ export function readInt8(buffer: Uint8Array, offset: number): number { throw new Error("Offset is outside the bounds of Uint8Array"); } - - const val = buffer[offset]; if (val <= 0x7f) { diff --git a/ts_src/index.ts b/ts_src/index.ts index 58d8eac..50f6924 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -266,8 +266,10 @@ export function writeInt64( throw new Error("Offset is outside the bounds of Uint8Array"); } - if(value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { - throw new Error(`The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}`); + if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) { + throw new Error( + `The value of "value" is out of range. It must be >= ${-0x8000000000000000n} and <= ${0x7fffffffffffffffn}. Received ${value}` + ); } littleEndian = littleEndian.toUpperCase() as endian; diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index 4efbb87..736b14f 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -557,7 +557,7 @@ describe(`Uint8Array tools`, () => { } for (const fixture of fixtures) { - expect(tools.writeInt32(arr, 0, fixture.value, "BE")).toEqual(4); + expect(tools.writeInt32(arr, 0, fixture.value, "BE")).toEqual(4); expect(arr).toEqual(fixture.expect.reverse()); } }); @@ -669,25 +669,34 @@ describe(`Uint8Array tools`, () => { it("signed integer functions should throw if the value is out of range", () => { const nums = [0, 1, 2, 3]; - for(let i = 0; i < nums.length; i++) { + for (let i = 0; i < nums.length; i++) { const bitLength = (1 << nums[i]) * 8; - const fnName = "writeInt" + (bitLength).toString(); - const rawLow = BigInt(-(2n ** BigInt(bitLength - 1))); + const fnName = "writeInt" + bitLength.toString(); + const rawLow = BigInt(-(2n ** BigInt(bitLength - 1))); const rawHigh = -rawLow - 1n; const rawHighValue = rawHigh + 1n; const rawLowValue = rawLow - 1n; const low = i === 3 ? rawLow : Number(rawLow); const high = i === 3 ? rawHigh : Number(rawHigh); - const values = [i === 3 ? rawLowValue : Number(rawLowValue), i === 3 ? rawHighValue : Number(rawHighValue)]; + const values = [ + i === 3 ? rawLowValue : Number(rawLowValue), + i === 3 ? rawHighValue : Number(rawHighValue), + ]; for (const value of values) { - for(const endian of ["BE", "LE"]) { + for (const endian of ["BE", "LE"]) { expect(() => - //@ts-ignore - tools[fnName](new Uint8Array(bitLength / 8 + 1), 0, value, endian) + tools[fnName]( + new Uint8Array(bitLength / 8 + 1), + 0, + value, + endian + ) ).toThrowError( - new Error(`The value of "value" is out of range. It must be >= ${low} and <= ${high}. Received ${value}`) + new Error( + `The value of "value" is out of range. It must be >= ${low} and <= ${high}. Received ${value}` + ) ); } } @@ -705,7 +714,6 @@ describe(`Uint8Array tools`, () => { const val = j === 4 ? 1n : 1; for (const endian of ["BE", "LE"]) { expect(() => - // @ts-ignore tools[fnName](new Uint8Array(j + 1), val, j + 1, endian) ).toThrowError( new Error("Offset is outside the bounds of Uint8Array") From 430b9cbb00e9784ff573469cb05782cb3f534c17 Mon Sep 17 00:00:00 2001 From: ayman Date: Wed, 28 Aug 2024 22:00:47 +0530 Subject: [PATCH 6/8] fix: linting errors --- ts_src/tests.spec.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index 736b14f..f042ff7 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -687,6 +687,8 @@ describe(`Uint8Array tools`, () => { for (const value of values) { for (const endian of ["BE", "LE"]) { expect(() => + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore tools[fnName]( new Uint8Array(bitLength / 8 + 1), 0, @@ -714,6 +716,8 @@ describe(`Uint8Array tools`, () => { const val = j === 4 ? 1n : 1; for (const endian of ["BE", "LE"]) { expect(() => + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore tools[fnName](new Uint8Array(j + 1), val, j + 1, endian) ).toThrowError( new Error("Offset is outside the bounds of Uint8Array") From 6930b09eff5e70b91aefc76f3352d02732a00371 Mon Sep 17 00:00:00 2001 From: ayman Date: Thu, 29 Aug 2024 06:49:49 +0530 Subject: [PATCH 7/8] test: add intermediate values for signed integer read-write functions --- ts_src/tests.spec.ts | 233 ++++++++++++------------------------------- 1 file changed, 66 insertions(+), 167 deletions(-) diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index f042ff7..4f300ee 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -414,222 +414,129 @@ describe(`Uint8Array tools`, () => { it("should be able to writeInt8", () => { const arr = new Uint8Array(1); - const fixtures = [ - { - value: 1, - expect: Uint8Array.from([1]), - }, - { - value: 0x7f, - expect: Uint8Array.from([0x7f]), - }, - { - value: -0x80, - expect: Uint8Array.from([0x80]), - }, - { - value: -0x01, - expect: Uint8Array.from([0xff]), - }, - ]; + const fixtures = [1, 0x7f, 0x0f, 0x1f, -0x80, -0x01, -0x0f, -0x1f]; for (const fixture of fixtures) { - expect(tools.writeInt8(arr, 0, fixture.value)).toEqual(1); - expect(arr).toEqual(fixture.expect); + const expected = Buffer.alloc(1); + expected.writeInt8(fixture, 0); + expect(tools.writeInt8(arr, 0, fixture)).toEqual(1); + expect(arr).toEqual(Uint8Array.from(expected)); } }); it("should be able to readInt8", () => { const arr = new Uint8Array(1); - const fixtures = [ - { - value: 1, - expect: 1, - }, - { - value: 0x7f, - expect: 0x7f, - }, - { - value: -0x80, - expect: -0x80, - }, - { - value: -0x01, - expect: -0x01, - }, - ]; + const fixtures = [1, 0x7f, 0x0f, 0x1f, -0x80, -0x01, -0x0f, -0x1f]; for (const fixture of fixtures) { - tools.writeInt8(arr, 0, fixture.value); - expect(tools.readInt8(arr, 0)).toEqual(fixture.expect); + tools.writeInt8(arr, 0, fixture); + expect(tools.readInt8(arr, 0)).toEqual(fixture); } }); it("should be able to writeInt16", () => { const arr = new Uint8Array(2); + const fixtures = [ - { - value: 1, - expect: Uint8Array.from([1, 0]), - }, - { - value: 0x7fff, - expect: Uint8Array.from([0xff, 0x7f]), - }, - { - value: -0x8000, - expect: Uint8Array.from([0x00, 0x80]), - }, - { - value: -0x01, - expect: Uint8Array.from([0xff, 0xff]), - }, + 1, 0x7fff, 0x00ff, 0x01ff, -0x8000, -0x01, -0x00ff, -0x01ff, ]; + + const expected = Buffer.alloc(2); for (const fixture of fixtures) { - expect(tools.writeInt16(arr, 0, fixture.value, "LE")).toEqual(2); - expect(arr).toEqual(fixture.expect); + expected.writeInt16LE(fixture, 0); + expect(tools.writeInt16(arr, 0, fixture, "LE")).toEqual(2); + expect(arr).toEqual(Uint8Array.from(expected)); } for (const fixture of fixtures) { - expect(tools.writeInt16(arr, 0, fixture.value, "BE")).toEqual(2); - expect(arr).toEqual(fixture.expect.reverse()); + expected.writeInt16BE(fixture, 0); + expect(tools.writeInt16(arr, 0, fixture, "BE")).toEqual(2); + expect(arr).toEqual(Uint8Array.from(expected)); } }); it("should be able to readInt16", () => { const arr = new Uint8Array(2); const fixtures = [ - { - value: 1, - expect: 1, - }, - { - value: 0x7fff, - expect: 0x7fff, - }, - { - value: -0x8000, - expect: -0x8000, - }, - { - value: -0x01, - expect: -0x01, - }, + 1, 0x7fff, 0x00ff, 0x01ff, -0x8000, -0x01, -0x00ff, -0x01ff, ]; for (const fixture of fixtures) { - tools.writeInt16(arr, 0, fixture.value, "LE"); - expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture.expect); + tools.writeInt16(arr, 0, fixture, "LE"); + expect(tools.readInt16(arr, 0, "LE")).toEqual(fixture); } for (const fixture of fixtures) { - tools.writeInt16(arr, 0, fixture.value, "BE"); - expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture.expect); + tools.writeInt16(arr, 0, fixture, "BE"); + expect(tools.readInt16(arr, 0, "BE")).toEqual(fixture); } }); it("should be able to writeInt32", () => { const arr = new Uint8Array(4); const fixtures = [ - { - value: 1, - expect: Uint8Array.from([1, 0, 0, 0]), - }, - { - value: 0x7fffffff, - expect: Uint8Array.from([0xff, 0xff, 0xff, 0x7f]), - }, - { - value: -0x80000000, - expect: Uint8Array.from([0x00, 0x00, 0x00, 0x80]), - }, - { - value: -0x01, - expect: Uint8Array.from([0xff, 0xff, 0xff, 0xff]), - }, + 1, 0x7fffffff, 0x0000ffff, 0x0001ffff, -0x80000000, -0x01, + -0x0000ffff, -0x0001ffff, ]; + const expected = Buffer.alloc(4); for (const fixture of fixtures) { - expect(tools.writeInt32(arr, 0, fixture.value, "LE")).toEqual(4); - expect(arr).toEqual(fixture.expect); + expected.writeInt32LE(fixture, 0); + expect(tools.writeInt32(arr, 0, fixture, "LE")).toEqual(4); + expect(arr).toEqual(Uint8Array.from(expected)); } for (const fixture of fixtures) { - expect(tools.writeInt32(arr, 0, fixture.value, "BE")).toEqual(4); - expect(arr).toEqual(fixture.expect.reverse()); + expected.writeInt32BE(fixture, 0); + expect(tools.writeInt32(arr, 0, fixture, "BE")).toEqual(4); + expect(arr).toEqual(Uint8Array.from(expected)); } }); it("should be able to readInt32", () => { const arr = new Uint8Array(4); - const fixtures = [ - { - value: 1, - expect: 1, - }, - { - value: 0x7fffffff, - expect: 0x7fffffff, - }, - { - value: -0x80000000, - expect: -0x80000000, - }, - { - value: -0x01, - expect: -0x01, - }, + 1, 0x7fffffff, 0x0000ffff, 0x0001ffff, -0x80000000, -0x01, + -0x0000ffff, -0x0001ffff, ]; for (const fixture of fixtures) { - tools.writeInt32(arr, 0, fixture.value, "LE"); - expect(tools.readInt32(arr, 0, "LE")).toEqual(fixture.expect); + tools.writeInt32(arr, 0, fixture, "LE"); + expect(tools.readInt32(arr, 0, "LE")).toEqual(fixture); } for (const fixture of fixtures) { - tools.writeInt32(arr, 0, fixture.value, "BE"); - expect(tools.readInt32(arr, 0, "BE")).toEqual(fixture.expect); + tools.writeInt32(arr, 0, fixture, "BE"); + expect(tools.readInt32(arr, 0, "BE")).toEqual(fixture); } }); it("should be able to writeInt64", () => { const arr = new Uint8Array(8); + const fixtures = [ - { - value: 1n, - expect: Uint8Array.from([1, 0, 0, 0, 0, 0, 0, 0]), - }, - { - value: 0x7fffffffffffffffn, - expect: Uint8Array.from([ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - ]), - }, - { - value: -0x8000000000000000n, - expect: Uint8Array.from([ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - ]), - }, - { - value: -0x01n, - expect: Uint8Array.from([ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - ]), - }, + 1n, + 0x7fffffffffffffffn, + 0x00000000ffffffffn, + 0x00000001ffffffffn, + -0x8000000000000000n, + -0x01n, + -0x00000000ffffffffn, + -0x00000001ffffffffn, ]; + const expected = Buffer.alloc(8); for (const fixture of fixtures) { - expect(tools.writeInt64(arr, 0, fixture.value, "LE")).toEqual(8); - expect(arr).toEqual(fixture.expect); + expected.writeBigInt64LE(fixture, 0); + expect(tools.writeInt64(arr, 0, fixture, "LE")).toEqual(8); + expect(arr).toEqual(Uint8Array.from(expected)); } for (const fixture of fixtures) { - expect(tools.writeInt64(arr, 0, fixture.value, "BE")).toEqual(8); - expect(arr).toEqual(fixture.expect.reverse()); + expected.writeBigInt64BE(fixture, 0); + expect(tools.writeInt64(arr, 0, fixture, "BE")).toEqual(8); + expect(arr).toEqual(Uint8Array.from(expected)); } }); @@ -637,32 +544,24 @@ describe(`Uint8Array tools`, () => { const arr = new Uint8Array(8); const fixtures = [ - { - value: 1n, - expect: 1n, - }, - { - value: 0x7fffffffffffffffn, - expect: 0x7fffffffffffffffn, - }, - { - value: -0x8000000000000000n, - expect: -0x8000000000000000n, - }, - { - value: -0x01n, - expect: -0x01n, - }, + 1n, + 0x7fffffffffffffffn, + 0x00000000ffffffffn, + 0x00000001ffffffffn, + -0x8000000000000000n, + -0x01n, + -0x00000000ffffffffn, + -0x00000001ffffffffn, ]; for (const fixture of fixtures) { - tools.writeInt64(arr, 0, fixture.value, "LE"); - expect(tools.readInt64(arr, 0, "LE")).toEqual(fixture.expect); + tools.writeInt64(arr, 0, fixture, "LE"); + expect(tools.readInt64(arr, 0, "LE")).toEqual(fixture); } for (const fixture of fixtures) { - tools.writeInt64(arr, 0, fixture.value, "BE"); - expect(tools.readInt64(arr, 0, "BE")).toEqual(fixture.expect); + tools.writeInt64(arr, 0, fixture, "BE"); + expect(tools.readInt64(arr, 0, "BE")).toEqual(fixture); } }); From 4d2d33f85967d059066952f82f2b6491a751f8f2 Mon Sep 17 00:00:00 2001 From: ayman Date: Thu, 29 Aug 2024 06:51:21 +0530 Subject: [PATCH 8/8] lint: remove empty line --- ts_src/tests.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts_src/tests.spec.ts b/ts_src/tests.spec.ts index 4f300ee..b5686a3 100644 --- a/ts_src/tests.spec.ts +++ b/ts_src/tests.spec.ts @@ -440,7 +440,6 @@ describe(`Uint8Array tools`, () => { const fixtures = [ 1, 0x7fff, 0x00ff, 0x01ff, -0x8000, -0x01, -0x00ff, -0x01ff, ]; - const expected = Buffer.alloc(2); for (const fixture of fixtures) {