diff --git a/src/utils/number_utils.ts b/src/utils/number_utils.ts index a3ccc8e2..cb197968 100644 --- a/src/utils/number_utils.ts +++ b/src/utils/number_utils.ts @@ -39,14 +39,23 @@ export const NumberUtils = { /** Reads a little-endian 64-bit integer from source */ getBigInt64LE(source: Uint8Array, offset: number): bigint { - const lo = NumberUtils.getUint32LE(source, offset); - const hi = NumberUtils.getUint32LE(source, offset + 4); + // eslint-disable-next-line no-restricted-globals + const hi = BigInt( + source[offset + 4] + + source[offset + 5] * 256 + + source[offset + 6] * 65536 + + (source[offset + 7] << 24) + ); // Overflow - /* - eslint-disable-next-line no-restricted-globals - -- This is allowed since this helper should not be called unless bigint features are enabled - */ - return (BigInt(hi) << BigInt(32)) + BigInt(lo); + // eslint-disable-next-line no-restricted-globals + const lo = BigInt( + source[offset] + + source[offset + 1] * 256 + + source[offset + 2] * 65536 + + source[offset + 3] * 16777216 + ); + // eslint-disable-next-line no-restricted-globals + return (hi << BigInt(32)) + lo; }, /** Reads a little-endian 64-bit float from source */ diff --git a/test/node/bigint.test.ts b/test/node/bigint.test.ts index 9532859f..3ffca593 100644 --- a/test/node/bigint.test.ts +++ b/test/node/bigint.test.ts @@ -105,6 +105,46 @@ describe('BSON BigInt support', function () { it(description, test); } + + it('correctly deserializes min 64 bit int (-2n**63n)', function () { + expect( + BSON.deserialize(Buffer.from('10000000126100000000000000008000', 'hex'), { + useBigInt64: true + }) + ).to.deep.equal({ a: -(2n ** 63n) }); + }); + + it('correctly deserializes -1n', function () { + expect( + BSON.deserialize(Buffer.from('10000000126100FFFFFFFFFFFFFFFF00', 'hex'), { + useBigInt64: true + }) + ).to.deep.equal({ a: -1n }); + }); + + it('correctly deserializes 0n', function () { + expect( + BSON.deserialize(Buffer.from('10000000126100000000000000000000', 'hex'), { + useBigInt64: true + }) + ).to.deep.equal({ a: 0n }); + }); + + it('correctly deserializes 1n', function () { + expect( + BSON.deserialize(Buffer.from('10000000126100010000000000000000', 'hex'), { + useBigInt64: true + }) + ).to.deep.equal({ a: 1n }); + }); + + it('correctly deserializes max 64 bit int (2n**63n -1n)', function () { + expect( + BSON.deserialize(Buffer.from('10000000126100FFFFFFFFFFFFFF7F00', 'hex'), { + useBigInt64: true + }) + ).to.deep.equal({ a: 2n ** 63n - 1n }); + }); }); describe('BSON.serialize()', function () {