diff --git a/CHANGELOG.md b/CHANGELOG.md
index 942c4e7c1..355b79907 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# CHANGELOG
+## master
+
+Changes:
+
+- Optimize `u8aToHex` with direct (non-hex) conversion
+
+
## 9.1.1 Apr 30, 2022
Contributed:
diff --git a/packages/util/src/compact/fromU8a.spec.ts b/packages/util/src/compact/fromU8a.spec.ts
index 915017c7a..4be95136f 100644
--- a/packages/util/src/compact/fromU8a.spec.ts
+++ b/packages/util/src/compact/fromU8a.spec.ts
@@ -14,16 +14,17 @@ describe('compactFromU8a', (): void => {
it('decodes from same u16 encoded value', (): void => {
expect(
- compactFromU8a(new Uint8Array([0b11111101, 0b00000111]))
- ).toEqual([2, new BN(511)]);
+ compactFromU8a(new Uint8Array([0b11111101, 0b00000111])).toString()
+ ).toEqual(
+ [2, new BN(511)].toString()
+ );
});
it('decodes from same u32 encoded value (short)', (): void => {
expect(
- compactFromU8a(new Uint8Array([254, 255, 3, 0]))
+ compactFromU8a(new Uint8Array([254, 255, 3, 0])).toString()
).toEqual(
- // since we use in-place, the words are different... HACK it
- [4, new BN(0xffff).ishln(16).ishrn(16)]
+ [4, new BN(0xffff)].toString()
);
});
diff --git a/packages/util/src/compact/fromU8a.ts b/packages/util/src/compact/fromU8a.ts
index f0913fa17..4ad99fbcf 100644
--- a/packages/util/src/compact/fromU8a.ts
+++ b/packages/util/src/compact/fromU8a.ts
@@ -3,12 +3,12 @@
import type { U8aLike } from '../types';
-import { BN, BN_FOUR } from '../bn';
+import { BN, BN_FIVE } from '../bn';
import { u8aToBn, u8aToU8a } from '../u8a';
/**
* @name compactFromU8a
- * @description Retrievs the offset and encoded length from a compact-prefixed value
+ * @description Retrives the offset and encoded length from a compact-prefixed value
* @example
*
*
@@ -32,12 +32,10 @@ export function compactFromU8a (input: U8aLike): [number, BN] {
return [4, u8aToBn(u8a.subarray(0, 4), true).ishrn(2)];
}
- const offset = 1 + (
- new BN(u8a[0])
- .ishrn(2) // clear flag
- .iadd(BN_FOUR) // add 4 for base length
- .toNumber()
- );
+ const offset = new BN(u8a[0])
+ .ishrn(2) // clear flag
+ .iadd(BN_FIVE) // add 4 for base length, 1 for this byte
+ .toNumber();
return [offset, u8aToBn(u8a.subarray(1, offset), true)];
}
diff --git a/packages/util/src/hex/toBn.ts b/packages/util/src/hex/toBn.ts
index 94dde73e8..0d6eaa86e 100644
--- a/packages/util/src/hex/toBn.ts
+++ b/packages/util/src/hex/toBn.ts
@@ -8,8 +8,6 @@ import { isBoolean } from '../is/boolean';
import { objectSpread } from '../object/spread';
import { hexStripPrefix } from './stripPrefix';
-const DEFAULT_OPTS: ToBnOptions = { isLe: false, isNegative: false };
-
/**
* @name hexToBn
* @summary Creates a BN.js object from a hex string.
@@ -28,12 +26,13 @@ const DEFAULT_OPTS: ToBnOptions = { isLe: false, isNegative: false };
* hexToBn('0x123480001f'); // => BN(0x123480001f)
* ```
*/
-export function hexToBn (value?: string | null, options: ToBnOptions | boolean = DEFAULT_OPTS): BN {
+export function hexToBn (value?: string | null, options: ToBnOptions | boolean = {}): BN {
if (!value || value === '0x') {
return new BN(0);
}
- const { isLe, isNegative }: ToBnOptions = objectSpread(
+ // For hex, default to BE
+ const { isLe, isNegative } = objectSpread(
{ isLe: false, isNegative: false },
isBoolean(options)
? { isLe: options }
@@ -43,7 +42,7 @@ export function hexToBn (value?: string | null, options: ToBnOptions | boolean =
const bn = new BN(stripped, 16, isLe ? 'le' : 'be');
// fromTwos takes as parameter the number of bits, which is the hex length
- // multiplied by 4.
+ // multiplied by 4 (2 bytes being 8 bits)
return isNegative
? bn.fromTwos(stripped.length * 4)
: bn;
diff --git a/packages/util/src/u8a/toBigInt.spec.ts b/packages/util/src/u8a/toBigInt.spec.ts
index d15497121..6be9ad183 100644
--- a/packages/util/src/u8a/toBigInt.spec.ts
+++ b/packages/util/src/u8a/toBigInt.spec.ts
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
+import { performance } from '../test/performance';
import { u8aToBigInt } from '.';
describe('u8aToBigInt', (): void => {
@@ -56,4 +57,6 @@ describe('u8aToBigInt', (): void => {
)
).toEqual(-1234n);
});
+
+ performance('u8aToBigInt', 500000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBigInt);
});
diff --git a/packages/util/src/u8a/toBigInt.ts b/packages/util/src/u8a/toBigInt.ts
index 5d135708b..68a52e1bc 100644
--- a/packages/util/src/u8a/toBigInt.ts
+++ b/packages/util/src/u8a/toBigInt.ts
@@ -55,7 +55,7 @@ export function u8aToBigInt (value: Uint8Array, options: ToBnOptions = {}): bigi
return BigInt(0);
}
- const { isLe, isNegative }: ToBnOptions = objectSpread({ isLe: true, isNegative: false }, options);
+ const { isLe, isNegative } = objectSpread({ isLe: true, isNegative: false }, options);
const u8a = isLe
? value.reverse()
: value;
diff --git a/packages/util/src/u8a/toBn.spec.ts b/packages/util/src/u8a/toBn.spec.ts
index 2565efe2a..5d8e06e53 100644
--- a/packages/util/src/u8a/toBn.spec.ts
+++ b/packages/util/src/u8a/toBn.spec.ts
@@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
+import { performance } from '../test/performance';
import { u8aToBn } from '.';
describe('u8aToBn', (): void => {
@@ -89,4 +90,6 @@ describe('u8aToBn', (): void => {
)
).toBe(true);
});
+
+ performance('u8aToBn', 500000, [[new Uint8Array([0x68, 0x65, 0x6c, 0x6c])]], u8aToBn);
});
diff --git a/packages/util/src/u8a/toBn.ts b/packages/util/src/u8a/toBn.ts
index 8cbf3b811..095b431cc 100644
--- a/packages/util/src/u8a/toBn.ts
+++ b/packages/util/src/u8a/toBn.ts
@@ -1,13 +1,11 @@
// Copyright 2017-2022 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
-import type { BN } from '../bn/bn';
import type { ToBnOptions } from '../types';
-import { hexToBn } from '../hex/toBn';
-import { u8aToHex } from './toHex';
-
-const DEFAULT_OPTS: ToBnOptions = { isLe: true, isNegative: false };
+import { BN } from '../bn/bn';
+import { isBoolean } from '../is/boolean';
+import { objectSpread } from '../object/spread';
/**
* @name u8aToBn
@@ -27,9 +25,18 @@ const DEFAULT_OPTS: ToBnOptions = { isLe: true, isNegative: false };
* u8aToHex(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0xf])); // 0x68656c0f
* ```
*/
-export function u8aToBn (value: Uint8Array, options: ToBnOptions | boolean = DEFAULT_OPTS): BN {
- return hexToBn(
- u8aToHex(value),
- options
+export function u8aToBn (value: Uint8Array, options: ToBnOptions | boolean = {}): BN {
+ // NOTE: This is the same process as followed in the hex conversion
+ // For Uint8Array, default to LE
+ const { isLe, isNegative } = objectSpread(
+ { isLe: true, isNegative: false },
+ isBoolean(options)
+ ? { isLe: options }
+ : options
);
+ const bn = new BN(value, isLe ? 'le' : 'be');
+
+ return isNegative
+ ? bn.fromTwos(value.length * 8)
+ : bn;
}