Additional bigint utilities (#1194)

* Additional bigint utilities

* Adjust tests

* biTo{Hex, U8a}

* Adjust

* Ordering

* biSqrt

* Fix toU8a

* Extensible BigInt

* Class TS issues....

* Move type def to types

* Update packages/util/src/bi/sqrt.spec.ts

* max/min

* min/max tests
This commit is contained in:
Jaco
2021-11-16 20:27:19 +02:00
committed by GitHub
parent 87afdb1d86
commit fa5b5bca7e
24 changed files with 703 additions and 18 deletions
+69
View File
@@ -0,0 +1,69 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { isBigInt } from '../is';
import { BigIntClass } from '.';
describe('BigIntClass', (): void => {
it('has the correct valueOf', (): void => {
expect(
typeof new BigIntClass(0).valueOf()
).toEqual('bigint');
});
it('has the correct instanceof', (): void => {
expect(
isBigInt(new BigIntClass(0))
).toEqual(true);
});
it('has a top-level toString method', (): void => {
const test = new BigIntClass(16);
expect(test.toString()).toEqual('16');
expect(test.toString(16)).toEqual('10');
});
it('cane be added together', (): void => {
expect(new BigIntClass(16) + new BigIntClass(10)).toEqual(26n);
});
it('has the correct type for inherited', (): void => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
class Test extends BigIntClass implements BigInt {
}
expect(isBigInt(new Test(0x16))).toEqual(true);
});
it('inhertited class has own methods', (): void => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
class Test extends BigIntClass {
toHex (): string {
return `0x${(this as unknown as bigint).toString(16)}`;
}
}
expect(new Test(0x16).toHex()).toEqual('0x16');
});
it('inhertited class still acts like bigint', (): void => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
class Test extends BigIntClass {
// nothing
}
const test = new Test(0x16n);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(test.toString(16)).toEqual('16');
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(test * 2n).toEqual(44n);
});
});
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { IBigIntConstructor } from '../types';
// See https://stackoverflow.com/questions/58207487/extend-object-wrappers-for-modern-primitives
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export class BigIntImpl extends BigInt implements BigInt {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
constructor (value: string | number | bigint | boolean): bigint {
const self = Object(BigInt(value)) as bigint;
Object.setPrototypeOf(self, new.target.prototype);
return self;
}
}
export const BigIntClass = BigIntImpl as IBigIntConstructor;
+26
View File
@@ -0,0 +1,26 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
/**
* @name BI_MILLION
* @summary BigInt constant for 1,000,000.
*/
export const BI_MILLION = BigInt(1_000_000);
/**
* @name BI_BILLION
* @summary BigInt constant for 1,000,000,000.
*/
export const BI_BILLION = BigInt(1_000_000_000);
/**
* @name BI_QUINTILL
* @summary BigInt constant for 1,000,000,000,000,000,000.
*/
export const BI_QUINTILL = BI_BILLION * BI_BILLION;
/**
* @name BI_MAX_INTEGER
* @summary BigInt constant for MAX_SAFE_INTEGER
*/
export const BI_MAX_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
+16
View File
@@ -0,0 +1,16 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
/**
* @summary Utility methods to convert to and from `bigint` objects
*/
export * from './consts';
export { BigIntClass } from './class';
export { biSqrt } from './sqrt';
export { biToBigInt } from './toBigInt';
export { biMax } from './max';
export { biMin } from './min';
export { biToHex } from './toHex';
export { biToU8a } from './toU8a';
+30
View File
@@ -0,0 +1,30 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { biMax } from '.';
describe('biMax', (): void => {
it('finds maximum', (): void => {
expect(
biMax(1n, 2n, 3n)
).toEqual(3n);
});
it('finds maximum', (): void => {
expect(
biMax(2n, 3n, 1n)
).toEqual(3n);
});
it('returns a single item', (): void => {
expect(
biMax(1n)
).toEqual(1n);
});
it('fails when no items are available', (): void => {
expect(
() => biMax()
).toThrow(/Must provide one or more bigint arguments/);
});
});
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert';
/**
* @name biMax
* @summary Finds and returns the highest value in an array of bigint.
*/
export function biMax (...items: bigint[]): bigint {
assert(items.length >= 1, 'Must provide one or more bigint arguments');
let result = items[0];
for (let i = 1; i < items.length; i++) {
if (items[i] > result) {
result = items[i];
}
}
return result;
}
+24
View File
@@ -0,0 +1,24 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { biMin } from '.';
describe('biMin', (): void => {
it('finds BN minimum', (): void => {
expect(
biMin(2n, 1n, 3n)
).toEqual(1n);
});
it('returns a single item', (): void => {
expect(
biMin(1n)
).toEqual(1n);
});
it('fails when no items are available', (): void => {
expect(
() => biMin()
).toThrow(/Must provide one or more bigint arguments/);
});
});
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { assert } from '../assert';
/**
* @name biMin
* @summary Finds and returns the lowest value in an array of bigint.
*/
export function biMin (...items: bigint[]): bigint {
assert(items.length >= 1, 'Must provide one or more bigint arguments');
let result = items[0];
for (let i = 1; i < items.length; i++) {
if (items[i] < result) {
result = items[i];
}
}
return result;
}
+42
View File
@@ -0,0 +1,42 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { BN } from '../bn';
import { biSqrt } from '.';
const TESTS: [string | number | BN | bigint, string | number][] = [
[0, 0],
[1, 1],
[4, 2],
[256 * 256, 256],
[Number.MAX_SAFE_INTEGER, 94906265],
[new BN(Number.MAX_SAFE_INTEGER).iaddn(256), 94906265],
[12345678n * 12345679n, 12345678],
// test cases below from https://github.com/Aisse-258/bigint-isqrt/blob/f5254b9750841959022461c1353437a07a08f501/test/sqrt-test.js
[
'54866395443885995655625',
'234235768925'
],
[
'82120471531550314555681345949499512621827274120673745141541602816614526075010755373654280259022317599142038423759320355177481886719814621305828811322920076213800348341464996337890625',
'9062034624274524065844376014975805577107171799890766992670739972241112960081909332275390625'
],
[
'2068290204957779940494571454815902632050207752627007664813877111611972735314294907791993008455381265730624848057015476004143868408297250386512042711005577373327434315310235583583151773358353534031397385969275475421659036494173765903706963544628565027679444680637920371210258368358706248446698622704138943704561842220533563976838506992543814273403403362954987589637283890281226038798503294069403370486523697009383229578343444337394508531937972775639593763364402389410142290440075517598007930025487176173228232153685095699851764630884360483051570513804913157899314303269924424908606245851172031453725690942288677622973423417902662711606364188470325930406288190754356367655606430407552275285889968860367977288564364154999338284288438279464648663835830140826171534470717958048887869721791862539529444820484648908879364324577951008050851801647916673254009490596379549192296404841454780884358889449367135382779230574781333008561195244620152128505091883408484094800737142399855337799331037607433934520934135669364954550499058123797911762228642423567268540444910163468496805547450495819213412636594319148417857753712526066272727725420886898680432958409892237191284583904066400736417812258327303739879128916456683685232170600928808798462776174857486589598776587550843543720784829419478239563366491666155716208452087857080883906200829769222868347286071365156305396955420561718593130305703074908891135467193627721682044757187980688062367562451981939375400543212890625',
'45478458691536369397924851088318871329614555665525810477032568598360481742967756704524034986984134271202405190906906195123751965012732122548540879928668891416468847696038707003466943811913626146981446753434347552196868717612248915137033581428310504778371173112125038060138252719589122657221314190626986951627417768579641354255445988772645883238873672997347648890137913979299598785628581961589739331483895853398160785485300758458294999124984266041998145956341386549681176624661615465976970855592467853824812945820721933491609237311130118125761849911376495970746282571994312288380577879004620824004760109618074670810797544446334767103935754106103208789391060008291027361311679876439695844637933763721093782805837690830230712890625'
]
];
describe('biSqrt', (): void => {
it('fails on < 0 roots', (): void => {
expect(
() => biSqrt(-1n)
).toThrow(/negative numbers is not supported/);
});
TESTS.forEach(([value, expected], index): void => {
it(`calcs for test #${index}`, (): void => {
expect(biSqrt(value) === BigInt(expected)).toEqual(true);
});
});
});
+41
View File
@@ -0,0 +1,41 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '../bn';
import type { ToBigInt, ToBn } from '../types';
import { assert } from '../assert';
import { BI_MAX_INTEGER } from './consts';
import { biToBigInt } from './toBigInt';
const SQRT_MAX_SAFE_INTEGER = 94906265n;
/**
* @name biSqrt
* @summary Calculates the integer square root of a bigint
*/
export function biSqrt <ExtToBn extends ToBn | ToBigInt> (value: ExtToBn | BN | bigint | string | number | null): bigint {
const n = biToBigInt(value);
assert(n >= 0n, 'square root of negative numbers is not supported');
// https://stackoverflow.com/questions/53683995/javascript-big-integer-square-root/
// shortcut <= 2^53 - 1 to use the JS utils
if (n <= BI_MAX_INTEGER) {
return BigInt(Math.floor(Math.sqrt(Number(n))));
}
// Use sqrt(MAX_SAFE_INTEGER) as starting point. since we already know the
// output will be larger than this, we expect this to be a safe start
let x0 = SQRT_MAX_SAFE_INTEGER;
while (true) {
const x1 = ((n / x0) + x0) >> 1n;
if (x0 === x1 || (x0 === (x1 - 1n))) {
return x0;
}
x0 = x1;
}
}
+67
View File
@@ -0,0 +1,67 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { BN } from '../bn';
import { biToBigInt } from '.';
describe('biToBigInt', (): void => {
it('converts null values to 0x00', (): void => {
expect(
biToBigInt(null)
).toEqual(0n);
});
it('converts 0x values to 0x00', (): void => {
expect(
biToBigInt('0x')
).toEqual(0n);
});
it('converts BN values to bigint', (): void => {
expect(
biToBigInt(new BN(128))
).toEqual(128n);
});
it('converts BigInt values to bigint', (): void => {
expect(
biToBigInt(128821n)
).toEqual(128821n);
});
it('converts number values to bigint', (): void => {
expect(
biToBigInt(128)
).toEqual(128n);
});
it('converts string to bigint', (): void => {
expect(
biToBigInt('123')
).toEqual(123n);
});
it('converts hex to bigint', (): void => {
expect(
biToBigInt('0x0123')
).toEqual(0x123n);
});
it('converts Compact to bigint (via toBn)', (): void => {
expect(
biToBigInt({
something: 'test',
toBn: () => new BN(1234)
})
).toEqual(1234n);
});
it('converts Compact to bigint (via toBigInt)', (): void => {
expect(
biToBigInt({
something: 'test',
toBigInt: () => 1234n
})
).toEqual(1234n);
});
});
+31
View File
@@ -0,0 +1,31 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '../bn/bn';
import type { HexString, ToBigInt, ToBn } from '../types';
import { hexToBigInt } from '../hex/toBigInt';
import { isBn } from '../is/bn';
import { isHex } from '../is/hex';
import { isToBigInt } from '../is/toBigInt';
import { isToBn } from '../is/toBn';
/**
* @name biToBigInt
* @summary Creates a bigInt value from a BN, bigint, string (base 10 or hex) or number input.
*/
export function biToBigInt <ExtToBn extends ToBigInt | ToBn> (value?: HexString | ExtToBn | BN | bigint | string | number | null): bigint {
return typeof value === 'bigint'
? value
: !value
? BigInt(0)
: isHex(value)
? hexToBigInt(value.toString())
: isBn(value)
? BigInt(value.toString())
: isToBigInt(value)
? value.toBigInt()
: isToBn(value)
? BigInt(value.toBn().toString())
: BigInt(value);
}
+48
View File
@@ -0,0 +1,48 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { biToHex } from '.';
describe('biToHex', (): void => {
it('converts null values to 0x00', (): void => {
expect(
biToHex(null)
).toBe('0x00');
});
it('converts values to a prefixed hex representation', (): void => {
expect(
biToHex(128)
).toBe('0x80');
});
it('converts values to a prefixed hex representation (bitLength)', (): void => {
expect(
biToHex(128n, { bitLength: 16 })
).toBe('0x0080');
});
it('converts values to a prefixed hex representation (bitLength + le)', (): void => {
expect(
biToHex(128, { bitLength: 16, isLe: true })
).toBe('0x8000');
});
it('converts values to a prefixed hex representation (LE)', (): void => {
expect(
biToHex(128, { bitLength: 16, isLe: true })
).toBe('0x8000');
});
it('handles negative numbers', (): void => {
expect(
biToHex(-1234, { isNegative: true })
).toBe('0xfb2e');
});
it('handles negative numbers (with bitLength)', (): void => {
expect(
biToHex(-1234, { bitLength: 32, isNegative: true })
).toBe('0xfffffb2e');
});
});
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '../bn/bn';
import type { HexString, ToBigInt, ToBn, ToBnOptions } from '../types';
import { objectSpread } from '../object/spread';
import { u8aToHex } from '../u8a';
import { biToU8a } from './toU8a';
interface Options extends ToBnOptions {
bitLength?: number;
}
const ZERO_STR = '0x00';
/**
* @name biToHex
* @summary Creates a hex value from a bigint object.
*/
export function biToHex <ExtToBn extends ToBn | ToBigInt> (value?: ExtToBn | BN | bigint | number | null, options?: Options): HexString {
if (!value) {
return ZERO_STR;
}
return u8aToHex(
biToU8a(value, objectSpread(
// We spread here, the default for hex values is BE (JSONRPC via substrate)
{ isLe: false, isNegative: false },
options
))
);
}
+54
View File
@@ -0,0 +1,54 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { biToU8a } from '.';
describe('biToU8a', (): void => {
it('converts null values to 0x00', (): void => {
expect(
biToU8a(null)
).toEqual(new Uint8Array());
});
it('converts null values to 0x00000000 (bitLength)', (): void => {
expect(
biToU8a(null, { bitLength: 32 })
).toEqual(new Uint8Array([0, 0, 0, 0]));
});
it('converts values to a prefixed hex representation', (): void => {
expect(
biToU8a(0x123456n, { isLe: false })
).toEqual(new Uint8Array([0x12, 0x34, 0x56]));
});
it('converts values to a prefixed hex representation (bitLength)', (): void => {
expect(
biToU8a(0x123456n, { bitLength: 32, isLe: false })
).toEqual(new Uint8Array([0x00, 0x12, 0x34, 0x56]));
});
it('converts using little endian (as set)', (): void => {
expect(
biToU8a(0x123456n, { bitLength: 32, isLe: true })
).toEqual(new Uint8Array([0x56, 0x34, 0x12, 0x00]));
});
it('converts negative numbers', (): void => {
expect(
biToU8a(-1234n, { isNegative: true })
).toEqual(new Uint8Array([46, 251]));
});
it('converts negative numbers (BE)', (): void => {
expect(
biToU8a(-1234n, { isLe: false, isNegative: true })
).toEqual(new Uint8Array([251, 46]));
});
it('converts negative numbers (bitLength)', (): void => {
expect(
biToU8a(-1234n, { bitLength: 32, isNegative: true })
).toEqual(new Uint8Array([46, 251, 255, 255]));
});
});
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '../bn/bn';
import type { ToBigInt, ToBn, ToBnOptions } from '../types';
import { objectSpread } from '../object/spread';
import { biToBigInt } from './toBigInt';
interface Options extends ToBnOptions {
bitLength?: number;
}
const DIV = 256n;
function createEmpty ({ bitLength = 0 }: Options): Uint8Array {
return bitLength === -1
? new Uint8Array()
: new Uint8Array(Math.ceil(bitLength / 8));
}
function toU8a (value: bigint, { isLe, isNegative }: Options): Uint8Array {
const arr: number[] = [];
if (isNegative) {
value = (value + 1n) * -1n;
}
while (value !== 0n) {
const mod = value % DIV;
const val = Number(
isNegative
? mod ^ 0xffn
: mod
);
if (isLe) {
arr.push(val);
} else {
arr.unshift(val);
}
value = (value - mod) / DIV;
}
return Uint8Array.from(arr);
}
/**
* @name biToU8a
* @summary Creates a Uint8Array object from a bigint.
*/
export function biToU8a <ExtToBn extends ToBn | ToBigInt> (value?: ExtToBn | BN | bigint | number | null, options?: Options): Uint8Array {
const opts: Options = objectSpread(
{ bitLength: -1, isLe: true, isNegative: false },
options
);
const valueBi = biToBigInt(value);
if (valueBi === 0n) {
return createEmpty(opts);
}
const u8a = toU8a(valueBi, opts);
if (opts.bitLength === -1) {
return u8a;
}
const byteLength = Math.ceil((opts.bitLength || 0) / 8);
const output = new Uint8Array(byteLength);
if (opts.isNegative) {
output.fill(0xff);
}
output.set(u8a, opts.isLe ? 0 : byteLength - u8a.length);
return output;
}
+14 -13
View File
@@ -1,11 +1,12 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { HexString, ToBn } from '../types';
import type { HexString, ToBigInt, ToBn } from '../types';
import { hexToBn } from '../hex/toBn';
import { isBigInt } from '../is/bigInt';
import { isHex } from '../is/hex';
import { isToBigInt } from '../is/toBigInt';
import { isToBn } from '../is/toBn';
import { BN } from './bn';
@@ -25,18 +26,18 @@ import { BN } from './bn';
* bnToBn(new BN(0x1234)); // => BN(0x1234)
* ```
*/
export function bnToBn <ExtToBn extends ToBn> (value?: HexString | ExtToBn | BN | bigint | string | number | null): BN {
if (!value) {
return new BN(0);
} else if (isHex(value)) {
return hexToBn(value.toString());
} else if (isBigInt(value)) {
return new BN(value.toString());
}
export function bnToBn <ExtToBn extends ToBigInt | ToBn> (value?: HexString | ExtToBn | BN | bigint | string | number | null): BN {
return BN.isBN(value)
? value
: isToBn(value)
? value.toBn()
: new BN(value);
: !value
? new BN(0)
: isHex(value)
? hexToBn(value.toString())
: isBigInt(value)
? new BN(value.toString())
: isToBn(value)
? value.toBn()
: isToBigInt(value)
? new BN(value.toBigInt().toString())
: new BN(value);
}
+1
View File
@@ -8,6 +8,7 @@ export { packageInfo } from './packageInfo';
export * from './array';
export * from './assert';
export * from './bi';
export * from './bn';
export * from './buffer';
export * from './compact';
+1 -1
View File
@@ -16,5 +16,5 @@
* ```
*/
export function isBigInt (value: unknown): value is bigint {
return typeof value === 'bigint';
return typeof value === 'bigint' || value instanceof BigInt;
}
+1
View File
@@ -24,6 +24,7 @@ export { isObject } from './object';
export { isObservable } from './observable';
export { isString } from './string';
export { isTestChain } from './testChain';
export { isToBigInt } from './toBigInt';
export { isToBn } from './toBn';
export { isU8a } from './u8a';
export { isUndefined } from './undefined';
+20
View File
@@ -0,0 +1,20 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { isToBigInt } from '.';
describe('isToBigInt', (): void => {
it('is false on no value', (): void => {
expect(isToBigInt()).toEqual(false);
});
it('is false on non-compact value', (): void => {
expect(isToBigInt(123)).toEqual(false);
});
it('is true when compact-like signature is found', (): void => {
expect(isToBigInt({
toBigInt: () => BigInt(1)
})).toEqual(true);
});
});
+10
View File
@@ -0,0 +1,10 @@
// Copyright 2017-2021 @polkadot/util authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { ToBigInt } from '../types';
import { isFunction } from './function';
export function isToBigInt (value?: unknown): value is ToBigInt {
return !!value && isFunction((value as ToBigInt).toBigInt);
}
+24
View File
@@ -9,6 +9,10 @@ export interface Constructor<T = any> {
new(...value: any[]): T;
}
export interface ToBigInt {
toBigInt: () => bigint;
}
export interface ToBn {
toBn: () => BN;
}
@@ -61,3 +65,23 @@ export type HexDigit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
export type HexString = `0x${string}`;
export type U8aLike = HexString | number[] | Buffer | Uint8Array | AnyString;
export interface IBigIntConstructor {
new (value: string | number | bigint | boolean): bigint;
/**
* Interprets the low bits of a BigInt as a 2's-complement signed integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asIntN (bits: number, int: bigint): bigint;
/**
* Interprets the low bits of a BigInt as an unsigned integer.
* All higher bits are discarded.
* @param bits The number of low bits to use
* @param int The BigInt whose bits to extract
*/
asUintN (bits: number, int: bigint): bigint;
}
+4 -4
View File
@@ -5,8 +5,8 @@ import type { ToBnOptions } from '../types';
import { objectSpread } from '../object/spread';
const U8_MULT = 256n;
const U16_MUL = U8_MULT * U8_MULT;
const U8_MAX = 256n;
const U16_MAX = U8_MAX * U8_MAX;
function xor (input: Uint8Array): Uint8Array {
const result = new Uint8Array(input.length);
@@ -33,11 +33,11 @@ function toBigInt (input: Uint8Array): bigint {
let result = BigInt(0);
for (let i = 0; i < length; i += 2) {
result = (result * U16_MUL) + BigInt(dvI.getUint16(i));
result = (result * U16_MAX) + BigInt(dvI.getUint16(i));
}
if (mod) {
result = (result * U8_MULT) + BigInt(dvI.getUint8(length));
result = (result * U8_MAX) + BigInt(dvI.getUint8(length));
}
return result;