@polkadot/util
Version:
A collection of useful utilities for @polkadot
105 lines • 4.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.u8aToBn = void 0;
const bn_js_1 = require("../bn/bn.js");
/**
* @name u8aToBn
* @summary Creates a BN from a Uint8Array object.
* @description
* `UInt8Array` input values return the actual BN. `null` or `undefined` values returns an `0x0` value.
* @param value The value to convert
* @param options Options to pass while converting
* @param options.isLe Convert using Little Endian (default)
* @param options.isNegative Convert using two's complement
* @example
* <BR>
*
* ```javascript
* import { u8aToBn } from '@polkadot/util';
*
* u8aToHex(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0xf])); // 0x68656c0f
* ```
*/
function u8aToBn(value, { isLe = true, isNegative = false } = {}) {
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 (count <= 6) {
if (isNegative) {
let result = 0;
if (isLe) {
// Most common case i{8, 16, 32} default LE SCALE-encoded
// For <= 32, we also optimize the xor to a single op
// (see the comments around unrolling in the next section)
switch (count) {
case 0:
return new bn_js_1.BN(0);
case 1:
result = value[0] ^ 255;
break;
case 2:
result = (value[0] + (value[1] << 8)) ^ 65535;
break;
case 3:
result = (value[0] + (value[1] << 8) + (value[2] << 16)) ^ 16777215;
break;
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
result = (value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295;
break;
case 5:
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295) + ((value[4] ^ 0xff) * 4294967296);
break;
default: // 6
result = ((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295) + (((value[4] + (value[5] << 8)) ^ 65535) * 4294967296);
break;
}
}
else {
for (let i = 0; i < count; i++) {
result = (result * 256) + (value[i] ^ 0xff);
}
}
return count
? new bn_js_1.BN((result * -1) - 1)
: new bn_js_1.BN(0);
}
else if (isLe) {
// Most common case - u{8, 16, 32} default LE SCALE-encoded
//
// There are some slight benefits in unrolling this specific loop,
// however it comes with diminishing returns since here the actual
// `new BN` does seem to take up the bulk of the time
switch (count) {
case 0:
return new bn_js_1.BN(0);
case 1:
return new bn_js_1.BN(value[0]);
case 2:
return new bn_js_1.BN(value[0] + (value[1] << 8));
case 3:
return new bn_js_1.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_js_1.BN(value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216));
case 5:
return new bn_js_1.BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 16777216));
default: // 6
return new bn_js_1.BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 16777216));
}
}
else {
let result = 0;
for (let i = 0; i < count; i++) {
result = (result * 256) + value[i];
}
return new bn_js_1.BN(result);
}
}
return isNegative
? new bn_js_1.BN(value, isLe ? 'le' : 'be').fromTwos(value.length * 8)
: new bn_js_1.BN(value, isLe ? 'le' : 'be');
}
exports.u8aToBn = u8aToBn;