Adjust BE u8aTo{Bn, BigInt, Number} check (#1868)
* Adjust BE u8aTo{Bn, BigInt, Numer} check
* Adjust function names (liberal find-and-replace)
This commit is contained in:
@@ -18,27 +18,28 @@ const U64_MAX = BigInt('0x10000000000000000');
|
||||
export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = false }: ToBnOptions = {}): bigint {
|
||||
// slice + reverse is expensive, however SCALE is LE by default so this is the path
|
||||
// we are most interested in (the BE is added for the sake of being comprehensive)
|
||||
const u8a = isLe
|
||||
? value
|
||||
: value.slice().reverse();
|
||||
const count = u8a.length;
|
||||
if (!isLe) {
|
||||
value = value.slice().reverse();
|
||||
}
|
||||
|
||||
if (isNegative && count && (u8a[count - 1] & 0x80)) {
|
||||
const count = value.length;
|
||||
|
||||
if (isNegative && count && (value[count - 1] & 0x80)) {
|
||||
switch (count) {
|
||||
case 0:
|
||||
return BigInt(0);
|
||||
|
||||
case 1:
|
||||
return BigInt(((u8a[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
return BigInt(((value[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
|
||||
case 2:
|
||||
return BigInt((((u8a[0] + (u8a[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
return BigInt((((value[0] + (value[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
|
||||
case 4:
|
||||
return BigInt((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
return BigInt((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
}
|
||||
|
||||
const dvI = new DataView(u8a.buffer, u8a.byteOffset);
|
||||
const dvI = new DataView(value.buffer, value.byteOffset);
|
||||
|
||||
if (count === 8) {
|
||||
return dvI.getBigInt64(0, true);
|
||||
@@ -52,7 +53,7 @@ export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = fals
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
result = (result * U8_MAX) + BigInt(u8a[0] ^ 0xff);
|
||||
result = (result * U8_MAX) + BigInt(value[0] ^ 0xff);
|
||||
}
|
||||
|
||||
return (result * -_1n) - _1n;
|
||||
@@ -63,16 +64,16 @@ export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = fals
|
||||
return BigInt(0);
|
||||
|
||||
case 1:
|
||||
return BigInt(u8a[0]);
|
||||
return BigInt(value[0]);
|
||||
|
||||
case 2:
|
||||
return BigInt(u8a[0] + (u8a[1] << 8));
|
||||
return BigInt(value[0] + (value[1] << 8));
|
||||
|
||||
case 4:
|
||||
return BigInt(u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00));
|
||||
return BigInt(value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00));
|
||||
}
|
||||
|
||||
const dvI = new DataView(u8a.buffer, u8a.byteOffset);
|
||||
const dvI = new DataView(value.buffer, value.byteOffset);
|
||||
|
||||
switch (count) {
|
||||
case 8:
|
||||
@@ -90,7 +91,7 @@ export function u8aToBigInt (value: Uint8Array, { isLe = true, isNegative = fals
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
result = (result * U8_MAX) + BigInt(u8a[0]);
|
||||
result = (result * U8_MAX) + BigInt(value[0]);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -26,14 +26,15 @@ import { BN } from '../bn/bn.js';
|
||||
export function u8aToBn (value: Uint8Array, { isLe = true, isNegative = false }: ToBnOptions = {}): BN {
|
||||
// slice + reverse is expensive, however SCALE is LE by default so this is the path
|
||||
// we are most interested in (the BE is added for the sake of being comprehensive)
|
||||
const u8a = isLe
|
||||
? value
|
||||
: value.slice().reverse();
|
||||
const count = u8a.length;
|
||||
if (!isLe) {
|
||||
value = value.slice().reverse();
|
||||
}
|
||||
|
||||
const count = value.length;
|
||||
|
||||
// shortcut for <= u48 values - in this case the manual conversion
|
||||
// here seems to be more efficient than passing the full array
|
||||
if (isNegative && count && (u8a[count - 1] & 0x80)) {
|
||||
if (isNegative && count && (value[count - 1] & 0x80)) {
|
||||
// Most common case i{8, 16, 32} default LE SCALE-encoded
|
||||
// For <= 32, we also optimize the xor to a single op
|
||||
switch (count) {
|
||||
@@ -41,27 +42,27 @@ export function u8aToBn (value: Uint8Array, { isLe = true, isNegative = false }:
|
||||
return new BN(0);
|
||||
|
||||
case 1:
|
||||
return new BN(((u8a[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
return new BN(((value[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
|
||||
case 2:
|
||||
return new BN((((u8a[0] + (u8a[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
return new BN((((value[0] + (value[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
|
||||
case 3:
|
||||
return new BN((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16)) ^ 0x00ff_ffff) * -1) - 1);
|
||||
return new BN((((value[0] + (value[1] << 8) + (value[2] << 16)) ^ 0x00ff_ffff) * -1) - 1);
|
||||
|
||||
case 4:
|
||||
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
|
||||
// 32-bit, in the case where the top-most bit is set this yields a negative value
|
||||
return new BN((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
return new BN((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
|
||||
case 5:
|
||||
return new BN(((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((u8a[4] ^ 0xff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
return new BN(((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((value[4] ^ 0xff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
|
||||
case 6:
|
||||
return new BN(((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((u8a[4] + (u8a[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
return new BN(((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((value[4] + (value[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
|
||||
default:
|
||||
return new BN(u8a, 'le').fromTwos(count * 8);
|
||||
return new BN(value, 'le').fromTwos(count * 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,26 +76,26 @@ export function u8aToBn (value: Uint8Array, { isLe = true, isNegative = false }:
|
||||
return new BN(0);
|
||||
|
||||
case 1:
|
||||
return new BN(u8a[0]);
|
||||
return new BN(value[0]);
|
||||
|
||||
case 2:
|
||||
return new BN(u8a[0] + (u8a[1] << 8));
|
||||
return new BN(value[0] + (value[1] << 8));
|
||||
|
||||
case 3:
|
||||
return new BN(u8a[0] + (u8a[1] << 8) + (u8a[2] << 16));
|
||||
return new BN(value[0] + (value[1] << 8) + (value[2] << 16));
|
||||
|
||||
case 4:
|
||||
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
|
||||
// 32-bit, in the case where the top-most bit is set this yields a negative value
|
||||
return new BN(u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00));
|
||||
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00));
|
||||
|
||||
case 5:
|
||||
return new BN(u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + ((u8a[3] + (u8a[4] << 8)) * 0x1_00_00_00));
|
||||
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 0x1_00_00_00));
|
||||
|
||||
case 6:
|
||||
return new BN(u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + ((u8a[3] + (u8a[4] << 8) + (u8a[5] << 16)) * 0x1_00_00_00));
|
||||
return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 0x1_00_00_00));
|
||||
|
||||
default:
|
||||
return new BN(u8a, 'le');
|
||||
return new BN(value, 'le');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,39 +10,40 @@ import type { ToBnOptions } from '../types.js';
|
||||
export function u8aToNumber (value: Uint8Array, { isLe = true, isNegative = false }: ToBnOptions = {}): number {
|
||||
// slice + reverse is expensive, however SCALE is LE by default so this is the path
|
||||
// we are most interested in (the BE is added for the sake of being comprehensive)
|
||||
const u8a = isLe
|
||||
? value
|
||||
: value.slice().reverse();
|
||||
const count = u8a.length;
|
||||
if (!isLe) {
|
||||
value = value.slice().reverse();
|
||||
}
|
||||
|
||||
const count = value.length;
|
||||
|
||||
// When the value is a i{8, 16, 24, 32, 40, 40} values and the top-most bit
|
||||
// indicates a signed value, we use a two's complement conversion. If one of these
|
||||
// flags are not set, we just do a normal unsigned conversion (the same shortcut
|
||||
// applies in both the u8aTo{BigInt, Bn} conversions as well)
|
||||
if (isNegative && count && (u8a[count - 1] & 0x80)) {
|
||||
if (isNegative && count && (value[count - 1] & 0x80)) {
|
||||
switch (count) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
return (((u8a[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
return (((value[0] ^ 0x0000_00ff) * -1) - 1);
|
||||
|
||||
case 2:
|
||||
return ((((u8a[0] + (u8a[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
return ((((value[0] + (value[1] << 8)) ^ 0x0000_ffff) * -1) - 1);
|
||||
|
||||
case 3:
|
||||
return ((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16)) ^ 0x00ff_ffff) * -1) - 1);
|
||||
return ((((value[0] + (value[1] << 8) + (value[2] << 16)) ^ 0x00ff_ffff) * -1) - 1);
|
||||
|
||||
case 4:
|
||||
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
|
||||
// 32-bit, in the case where the top-most bit is set this yields a negative value
|
||||
return ((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
return ((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) * -1) - 1);
|
||||
|
||||
case 5:
|
||||
return (((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((u8a[4] ^ 0xff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
return (((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + ((value[4] ^ 0xff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
|
||||
case 6:
|
||||
return (((((u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((u8a[4] + (u8a[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
return (((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00)) ^ 0xffff_ffff) + (((value[4] + (value[5] << 8)) ^ 0x0000_ffff) * 0x1_00_00_00_00)) * -1) - 1);
|
||||
|
||||
default:
|
||||
throw new Error('Value more than 48-bits cannot be reliably converted');
|
||||
@@ -54,24 +55,24 @@ export function u8aToNumber (value: Uint8Array, { isLe = true, isNegative = fals
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
return u8a[0];
|
||||
return value[0];
|
||||
|
||||
case 2:
|
||||
return u8a[0] + (u8a[1] << 8);
|
||||
return value[0] + (value[1] << 8);
|
||||
|
||||
case 3:
|
||||
return u8a[0] + (u8a[1] << 8) + (u8a[2] << 16);
|
||||
return value[0] + (value[1] << 8) + (value[2] << 16);
|
||||
|
||||
case 4:
|
||||
// for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
|
||||
// 32-bit, in the case where the top-most bit is set this yields a negative value
|
||||
return u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + (u8a[3] * 0x1_00_00_00);
|
||||
return value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 0x1_00_00_00);
|
||||
|
||||
case 5:
|
||||
return u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + ((u8a[3] + (u8a[4] << 8)) * 0x1_00_00_00);
|
||||
return value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 0x1_00_00_00);
|
||||
|
||||
case 6:
|
||||
return u8a[0] + (u8a[1] << 8) + (u8a[2] << 16) + ((u8a[3] + (u8a[4] << 8) + (u8a[5] << 16)) * 0x1_00_00_00);
|
||||
return value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 0x1_00_00_00);
|
||||
|
||||
default:
|
||||
throw new Error('Value more than 48-bits cannot be reliably converted');
|
||||
|
||||
Reference in New Issue
Block a user