From 9a0309869dc7fbe8b71a23cd04869d318d4d11ce Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Fri, 4 Oct 2024 22:08:04 +0100 Subject: [PATCH] Fix: Converting Large Numbers to BigInt (#1019) * Fix converting large numbers to BigInts * Clarify numeric value * Add test --- src/value/convert/convert.ts | 2 +- test/runtime/value/convert/bigint.ts | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/value/convert/convert.ts b/src/value/convert/convert.ts index 92e6c58..a5ddf7b 100644 --- a/src/value/convert/convert.ts +++ b/src/value/convert/convert.ts @@ -120,7 +120,7 @@ function TryConvertBoolean(value: unknown) { } function TryConvertBigInt(value: unknown) { const truncateInteger = (value: string) => value.split('.')[0] - return IsStringNumeric(value) ? BigInt(truncateInteger(value)) : IsNumber(value) ? BigInt(value | 0) : IsValueFalse(value) ? BigInt(0) : IsValueTrue(value) ? BigInt(1) : value + return IsStringNumeric(value) ? BigInt(truncateInteger(value)) : IsNumber(value) ? BigInt(Math.trunc(value)) : IsValueFalse(value) ? BigInt(0) : IsValueTrue(value) ? BigInt(1) : value } function TryConvertString(value: unknown) { return IsValueToString(value) ? value.toString() : IsSymbol(value) && value.description !== undefined ? value.description.toString() : value diff --git a/test/runtime/value/convert/bigint.ts b/test/runtime/value/convert/bigint.ts index 383e692..02014a8 100644 --- a/test/runtime/value/convert/bigint.ts +++ b/test/runtime/value/convert/bigint.ts @@ -3,7 +3,7 @@ import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/BigInt', () => { - it('Should convert bitint from string 1', () => { + it('Should convert bigint from string 1', () => { const T = Type.BigInt() const R = Value.Convert(T, '1') Assert.IsEqual(R, BigInt(1)) @@ -13,7 +13,7 @@ describe('value/convert/BigInt', () => { const R = Value.Convert(T, '3.14') Assert.IsEqual(R, BigInt(3)) }) - it('Should convert bitint from string 3', () => { + it('Should convert bigint from string 3', () => { const T = Type.BigInt() const R = Value.Convert(T, 'true') Assert.IsEqual(R, BigInt(1)) @@ -43,7 +43,7 @@ describe('value/convert/BigInt', () => { const R = Value.Convert(T, '-12345678901234567890.123') Assert.IsEqual(R, BigInt('-12345678901234567890')) }) - it('Should convert bitint from number 1', () => { + it('Should convert bigint from number 1', () => { const T = Type.BigInt() const R = Value.Convert(T, 1) Assert.IsEqual(R, BigInt(1)) @@ -53,7 +53,27 @@ describe('value/convert/BigInt', () => { const R = Value.Convert(T, 3.14) Assert.IsEqual(R, BigInt(3)) }) - it('Should convert bitint from boolean 1', () => { + it('Should convert bigint from number 3', () => { + const T = Type.BigInt() + const R = Value.Convert(T, Math.pow(2, 31)) + Assert.IsEqual(R, BigInt(2147483648)) + }) + it('Should convert bigint from number 4', () => { + const T = Type.BigInt() + const R = Value.Convert(T, Number.MAX_SAFE_INTEGER) + Assert.IsEqual(R, BigInt(9007199254740991)) + }) + it('Should convert bigint from number 5', () => { + const T = Type.BigInt() + const R = Value.Convert(T, 123456789012345.6789) + Assert.IsEqual(R, BigInt(123456789012345)) + }) + it('Should convert bigint from number 6', () => { + const T = Type.BigInt() + const R = Value.Convert(T, -123456789012345.6789) + Assert.IsEqual(R, BigInt(-123456789012345)) + }) + it('Should convert bigint from boolean 1', () => { const T = Type.BigInt() const R = Value.Convert(T, true) Assert.IsEqual(R, BigInt(1))