diff --git a/packages/util/src/u8a/toBigInt.spec.ts b/packages/util/src/u8a/toBigInt.spec.ts index be1df7779..3585756c6 100644 --- a/packages/util/src/u8a/toBigInt.spec.ts +++ b/packages/util/src/u8a/toBigInt.spec.ts @@ -6,59 +6,266 @@ import { perf } from '../test/index.js'; import { u8aToBigInt } from './index.js'; +// test-cases are the same as in u8aToBn describe('u8aToBigInt', (): void => { it('converts little-endian by default', (): void => { expect( u8aToBigInt( new Uint8Array([0x12, 0x34]) - ) - ).toEqual(0x3412n); + ).toString(16) + ).toBe('3412'); }); - it('converts values (big-endian)', (): void => { - expect( - u8aToBigInt( - new Uint8Array([0x12, 0x34]), - { isLe: false } - ) - ).toEqual(0x1234n); + describe('LE', (): void => { + describe('unsigned', (): void => { + it('converts values (u8)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12]), + { isLe: true } + ).toString(16) + ).toBe('12'); + }); + + it('converts values (u16)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34]), + { isLe: true } + ).toString(16) + ).toBe('3412'); + }); + + it('converts values (u24)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56]), + { isLe: true } + ).toString(16) + ).toBe('563412'); + }); + + it('converts values (u32)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78]), + { isLe: true } + ).toString(16) + ).toBe('78563412'); + }); + + it('converts values (u40)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a]), + { isLe: true } + ).toString(16) + ).toBe('9a78563412'); + }); + + it('converts values (u48)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]), + { isLe: true } + ).toString(16) + ).toBe('bc9a78563412'); + }); + }); + + describe('signed', (): void => { + it('converts values (i8)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([244]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-12'); + }); + + it('converts values (i16)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([46, 251]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-1234'); + }); + + it('converts values (i24)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([192, 29, 254]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-123456'); + }); + + it('converts values (i32)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([235, 50, 164, 248]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-123456789'); + }); + + it('converts values (i40)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([65, 86, 129, 173, 254]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-5678999999'); + }); + + it('converts values (i48)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([1, 96, 141, 177, 231, 246]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-9999999999999'); + }); + + it('converts values (i64)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([1, 0, 156, 88, 76, 73, 31, 242]), + { isLe: true, isNegative: true } + ).toString() + ).toBe('-999999999999999999'); + }); + }); }); - it('converts values (little-endian)', (): void => { + describe('BE', (): void => { + it('converts values (u8)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12]), + { isLe: false } + ).toString(16) + ).toBe('12'); + }); + + it('converts values (u16)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34]), + { isLe: false } + ).toString(16) + ).toBe('1234'); + }); + + it('converts values (u24)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56]), + { isLe: false } + ).toString(16) + ).toBe('123456'); + }); + + it('converts values (u32)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78]), + { isLe: false } + ).toString(16) + ).toBe('12345678'); + }); + + it('converts values (u40)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a]), + { isLe: false } + ).toString(16) + ).toBe('123456789a'); + }); + + it('converts values (u48)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]), + { isLe: false } + ).toString(16) + ).toBe('123456789abc'); + }); + }); + + describe('empty creation', (): void => { + it('handles unsigned (le)', (): void => { + expect( + u8aToBigInt( + new Uint8Array(), + { isLe: true } + ).toString(16) + ).toBe('0'); + }); + + it('handles signed (le)', (): void => { + expect( + u8aToBigInt( + new Uint8Array(), + { isLe: true, isNegative: true } + ).toString(16) + ).toBe('0'); + }); + + it('handles unsigned (be)', (): void => { + expect( + u8aToBigInt( + new Uint8Array(), + { isLe: false } + ).toString(16) + ).toBe('0'); + }); + + it('handles signed (be)', (): void => { + expect( + u8aToBigInt( + new Uint8Array(), + { isLe: false, isNegative: true } + ).toString(16) + ).toBe('0'); + }); + }); + + describe('negative', (): void => { + it('handles negative numbers (little-endian)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([46, 251]), + { isLe: true, isNegative: true } + ) + ).toBe(-1234n); + }); + + it('handles negative numbers (big-endian)', (): void => { + expect( + u8aToBigInt( + new Uint8Array([251, 46]), + { isLe: false, isNegative: true } + ) + ).toBe(-1234n); + }); + }); + + it('handles overflows correctly (little-endian)', (): void => { expect( u8aToBigInt( - new Uint8Array([0x12, 0x34, 0x56]), + new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0]), { isLe: true } ) - ).toEqual(0x563412n); + ).toBe(256n); }); - it('converts empty', (): void => { - expect( - u8aToBigInt( - new Uint8Array(), - { isLe: true } - ) - ).toEqual(0n); - }); + perf('u8aToBigInt (u32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBigInt); + perf('u8aToBigInt (i32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], (v: Uint8Array) => u8aToBigInt(v, { isNegative: true })); + perf('u8aToBigInt (u64)', 500_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x68, 0x65, 0x6c, 0x6c])]], u8aToBigInt); - it('handles negative numbers (little-endian)', (): void => { - expect( - u8aToBigInt( - new Uint8Array([192, 29, 254]), - { isLe: true, isNegative: true } - ) - ).toEqual(-123456n); - }); - - it('handles negative numbers (big-endian)', (): void => { - expect( - u8aToBigInt( - new Uint8Array([251, 46]), - { isLe: false, isNegative: true } - ) - ).toEqual(-1234n); - }); - - perf('u8aToBigInt', 500000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBigInt); + // perf('BigInt (constructor)', 1_000_000, [[12345678]], (v: number) => BigInt(v).toString()); + // perf('BigInt (constructor -> string)', 1_000_000, [[12345678]], (v: number) => BigInt(v).toString()); }); diff --git a/packages/util/src/u8a/toBigInt.ts b/packages/util/src/u8a/toBigInt.ts index 79abee417..07fd46503 100644 --- a/packages/util/src/u8a/toBigInt.ts +++ b/packages/util/src/u8a/toBigInt.ts @@ -22,28 +22,28 @@ export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = fals const u8a = isLe ? value : value.reverse(); - const dvI = new DataView(u8a.buffer, u8a.byteOffset); - const mod = u8a.length % 2; + const count = u8a.length; + const mod = count % 2; let result = BigInt(0); // This is mostly written for readability (with the single isNegative shortcut), // as opposed to performance, e.g. `u8aToBn` does loop unrolling, etc. if (isNegative) { - for (let i = u8a.length - 2; i >= mod; i -= 2) { + for (let i = count - 2; i >= mod; i -= 2) { result = (result * U16_MAX) + BigInt(dvI.getUint16(i, true) ^ 0xffff); } if (mod) { - result = (result * U8_MAX) + BigInt(dvI.getUint8(0) ^ 0xff); + result = (result * U8_MAX) + BigInt(u8a[0] ^ 0xff); } } else { - for (let i = u8a.length - 2; i >= mod; i -= 2) { + for (let i = count - 2; i >= mod; i -= 2) { result = (result * U16_MAX) + BigInt(dvI.getUint16(i, true)); } if (mod) { - result = (result * U8_MAX) + BigInt(dvI.getUint8(0)); + result = (result * U8_MAX) + BigInt(u8a[0]); } } diff --git a/packages/util/src/u8a/toBn.spec.ts b/packages/util/src/u8a/toBn.spec.ts index 1beefda37..73c6d6164 100644 --- a/packages/util/src/u8a/toBn.spec.ts +++ b/packages/util/src/u8a/toBn.spec.ts @@ -3,9 +3,11 @@ /// +// import { BN } from '../bn/index.js'; import { perf } from '../test/index.js'; import { u8aToBn } from './index.js'; +// test-cases are the same as in u8aToBigInt describe('u8aToBn', (): void => { it('converts little-endian by default', (): void => { expect( @@ -264,4 +266,7 @@ describe('u8aToBn', (): void => { perf('u8aToBn (u32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBn); perf('u8aToBn (i32)', 1_000_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], (v: Uint8Array) => u8aToBn(v, { isNegative: true })); perf('u8aToBn (u64)', 500_000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0x68, 0x65, 0x6c, 0x6c])]], u8aToBn); + + // perf('BN (constructor)', 1_000_000, [[12345678]], (v: number) => new BN(v)); + // perf('BN (constructor -> string)', 1_000_000, [[12345678]], (v: number) => new BN(v).toString()); });