Optimize u8aToHex with direct (non-hex) conversion (#1477)

* Optimize `u8aToHex` with direct (non-hex) conversion

* Adjust compactFromU8a tests
This commit is contained in:
Jaco
2022-05-07 11:54:08 +03:00
committed by GitHub
parent bb1ed6cfcd
commit 7341c32df5
8 changed files with 46 additions and 28 deletions
+6 -5
View File
@@ -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()
);
});
+6 -8
View File
@@ -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
* <BR>
*
@@ -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)];
}
+4 -5
View File
@@ -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<ToBnOptions>(
{ 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;
+3
View File
@@ -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);
});
+1 -1
View File
@@ -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<ToBnOptions>({ isLe: true, isNegative: false }, options);
const u8a = isLe
? value.reverse()
: value;
+3
View File
@@ -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);
});
+16 -9
View File
@@ -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<ToBnOptions>(
{ 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;
}