UNPKG

3.71 kBJavaScriptView Raw
1import { BN } from '../bn/bn.js';
2/**
3 * @name u8aToBn
4 * @summary Creates a BN from a Uint8Array object.
5 * @description
6 * `UInt8Array` input values return the actual BN. `null` or `undefined` values returns an `0x0` value.
7 * @param value The value to convert
8 * @param options Options to pass while converting
9 * @param options.isLe Convert using Little Endian (default)
10 * @param options.isNegative Convert using two's complement
11 * @example
12 * <BR>
13 *
14 * ```javascript
15 * import { u8aToBn } from '@polkadot/util';
16 *
17 * u8aToHex(new Uint8Array([0x68, 0x65, 0x6c, 0x6c, 0xf])); // 0x68656c0f
18 * ```
19 */
20export function u8aToBn(value, { isLe = true, isNegative = false } = {}) {
21 // slice + reverse is expensive, however SCALE is LE by default so this is the path
22 // we are most interested in (the BE is added for the sake of being comprehensive)
23 if (!isLe) {
24 value = value.slice().reverse();
25 }
26 const count = value.length;
27 // shortcut for <= u48 values - in this case the manual conversion
28 // here seems to be more efficient than passing the full array
29 if (isNegative && count && (value[count - 1] & 0x80)) {
30 // Most common case i{8, 16, 32} default LE SCALE-encoded
31 // For <= 32, we also optimize the xor to a single op
32 switch (count) {
33 case 0:
34 return new BN(0);
35 case 1:
36 return new BN(((value[0] ^ 255) * -1) - 1);
37 case 2:
38 return new BN((((value[0] + (value[1] << 8)) ^ 65535) * -1) - 1);
39 case 3:
40 return new BN((((value[0] + (value[1] << 8) + (value[2] << 16)) ^ 16777215) * -1) - 1);
41 case 4:
42 // for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
43 // 32-bit, in the case where the top-most bit is set this yields a negative value
44 return new BN((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295) * -1) - 1);
45 case 5:
46 return new BN(((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295) + ((value[4] ^ 0xff) * 4294967296)) * -1) - 1);
47 case 6:
48 return new BN(((((value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216)) ^ 4294967295) + (((value[4] + (value[5] << 8)) ^ 65535) * 4294967296)) * -1) - 1);
49 default:
50 return new BN(value, 'le').fromTwos(count * 8);
51 }
52 }
53 // Most common case - u{8, 16, 32} default LE SCALE-encoded
54 //
55 // There are some slight benefits in unrolling this specific loop,
56 // however it comes with diminishing returns since here the actual
57 // `new BN` does seem to take up the bulk of the time
58 switch (count) {
59 case 0:
60 return new BN(0);
61 case 1:
62 return new BN(value[0]);
63 case 2:
64 return new BN(value[0] + (value[1] << 8));
65 case 3:
66 return new BN(value[0] + (value[1] << 8) + (value[2] << 16));
67 case 4:
68 // for the 3rd byte, we don't << 24 - since JS converts all bitwise operators to
69 // 32-bit, in the case where the top-most bit is set this yields a negative value
70 return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + (value[3] * 16777216));
71 case 5:
72 return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8)) * 16777216));
73 case 6:
74 return new BN(value[0] + (value[1] << 8) + (value[2] << 16) + ((value[3] + (value[4] << 8) + (value[5] << 16)) * 16777216));
75 default:
76 return new BN(value, 'le');
77 }
78}