diff --git a/src/Encoder.ts b/src/Encoder.ts index b047c1d..0ac65f8 100644 --- a/src/Encoder.ts +++ b/src/Encoder.ts @@ -291,6 +291,9 @@ export class Encoder { } private encodeBigInt64(object: bigint): void { + if (object < -(BigInt(2) ** BigInt(63)) || object > BigInt(2) ** BigInt(64) - BigInt(1)) { + throw new Error(`Cannot encode BigInt as int64/uint64 because it is out of range: ${object}`); + } if (object >= BigInt(0)) { // uint 64 this.writeU8(0xcf); diff --git a/test/bigint64.test.ts b/test/bigint64.test.ts index e2bf08f..f6f5c96 100644 --- a/test/bigint64.test.ts +++ b/test/bigint64.test.ts @@ -35,4 +35,30 @@ describe("useBigInt64: true", () => { const encoded = encode(value, { useBigInt64: true }); assert.deepStrictEqual(decode(encoded, { useBigInt64: true }), value); }); + + it("round-trips the boundary values of int64/uint64", () => { + const values = [ + BigInt(0), + BigInt(42), + BigInt(2) ** BigInt(63) - BigInt(1), // max int64 + -(BigInt(2) ** BigInt(63)), // min int64 + BigInt(2) ** BigInt(64) - BigInt(1), // max uint64 + ]; + for (const value of values) { + const encoded = encode(value, { useBigInt64: true }); + assert.deepStrictEqual(decode(encoded, { useBigInt64: true }), value); + } + }); + + it("throws when a bigint is out of the int64/uint64 range", () => { + const values = [ + BigInt(2) ** BigInt(64), // uint64 max + 1 + BigInt(2) ** BigInt(64) + BigInt(1), + -(BigInt(2) ** BigInt(63)) - BigInt(1), // int64 min - 1 + -(BigInt(2) ** BigInt(100)), + ]; + for (const value of values) { + assert.throws(() => encode(value, { useBigInt64: true }), /out of range/); + } + }); });