diff --git a/README.md b/README.md index d200c0b..30be632 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,9 @@ Class to iterate through bytes string by parsing individual bytes ### Methods +- [BigInt](#gear-bigint) +- [String](#gear-string) +- [rest](#gear-rest) - [isEmpty](#gear-isempty) - [nextByte](#gear-nextbyte) - [nextBytes](#gear-nextbytes) @@ -277,6 +280,26 @@ Class to iterate through bytes string by parsing individual bytes - [nextUint160](#gear-nextuint160) - [nextUint256](#gear-nextuint256) +#### :gear: BigInt + +| Method | Type | +| ---------- | ---------- | +| `BigInt` | `(bytes: string) => BytesIter` | + +#### :gear: String + +| Method | Type | +| ---------- | ---------- | +| `String` | `(bytes: string) => BytesIter` | + +#### :gear: rest + +Returns all not consumed bytes + +| Method | Type | +| ---------- | ---------- | +| `rest` | `() => T` | + #### :gear: isEmpty | Method | Type | @@ -287,55 +310,55 @@ Class to iterate through bytes string by parsing individual bytes | Method | Type | | ---------- | ---------- | -| `nextByte` | `() => bigint` | +| `nextByte` | `() => T` | #### :gear: nextBytes | Method | Type | | ---------- | ---------- | -| `nextBytes` | `(n: number) => bigint` | +| `nextBytes` | `(n: number) => T` | #### :gear: nextUint8 | Method | Type | | ---------- | ---------- | -| `nextUint8` | `() => bigint` | +| `nextUint8` | `() => T` | #### :gear: nextUint16 | Method | Type | | ---------- | ---------- | -| `nextUint16` | `() => bigint` | +| `nextUint16` | `() => T` | #### :gear: nextUint24 | Method | Type | | ---------- | ---------- | -| `nextUint24` | `() => bigint` | +| `nextUint24` | `() => T` | #### :gear: nextUint32 | Method | Type | | ---------- | ---------- | -| `nextUint32` | `() => bigint` | +| `nextUint32` | `() => T` | #### :gear: nextUint128 | Method | Type | | ---------- | ---------- | -| `nextUint128` | `() => bigint` | +| `nextUint128` | `() => T` | #### :gear: nextUint160 | Method | Type | | ---------- | ---------- | -| `nextUint160` | `() => bigint` | +| `nextUint160` | `() => T` | #### :gear: nextUint256 | Method | Type | | ---------- | ---------- | -| `nextUint256` | `() => bigint` | +| `nextUint256` | `() => T` | ## :factory: BytesBuilder diff --git a/src/bytes-iter/bytes-iter.spec.ts b/src/bytes-iter/bytes-iter.spec.ts new file mode 100644 index 0000000..9422486 --- /dev/null +++ b/src/bytes-iter/bytes-iter.spec.ts @@ -0,0 +1,17 @@ +import {BytesIter} from './bytes-iter' + +describe('BytesIter', () => { + it('should iterate as BigInt ', () => { + const iter = BytesIter.BigInt('0xdeadbeef') + expect(iter.nextByte()).toEqual(BigInt(0xde)) + expect(iter.nextByte()).toEqual(BigInt(0xad)) + expect(iter.nextBytes(2)).toEqual(BigInt(0xbeef)) + }) + + it('should iterate as String ', () => { + const iter = BytesIter.String('0xdeadbeef') + expect(iter.nextByte()).toEqual('0xde') + expect(iter.nextByte()).toEqual('0xad') + expect(iter.nextBytes(2)).toEqual('0xbeef') + }) +}) diff --git a/src/bytes-iter/bytes-iter.ts b/src/bytes-iter/bytes-iter.ts index 3e87f1f..e06488c 100644 --- a/src/bytes-iter/bytes-iter.ts +++ b/src/bytes-iter/bytes-iter.ts @@ -6,29 +6,47 @@ import {add0x} from '../utils' * Class to iterate through bytes string by parsing individual bytes * * @example - * const iter = new BytesIter('0xdeadbeef') + * const iter = BytesIter.BigInt('0xdeadbeef') * iter.nextByte() == BigInt(0xde) * iter.nextByte() == BigInt(0xad) * iter.nextBytes(2) == BigInt(0xbeef) */ -export class BytesIter { +export class BytesIter { private bytes: string - constructor(bytes: string) { + private constructor( + bytes: string, + private readonly ResultType: (val: string) => T + ) { assert(isHexBytes(bytes), 'invalid bytes value') this.bytes = bytes.slice(2) // trim 0x } + static BigInt(bytes: string): BytesIter { + return new BytesIter(bytes, BigInt) + } + + static String(bytes: string): BytesIter { + return new BytesIter(bytes, String) + } + + /** + * Returns all not consumed bytes + */ + public rest(): T { + return this.ResultType(add0x(this.bytes)) + } + public isEmpty(): boolean { return this.bytes.length === 0 } - public nextByte(): bigint { + public nextByte(): T { return this.nextBytes(1) } - public nextBytes(n: number): bigint { + public nextBytes(n: number): T { const cnt = n * 2 if (this.bytes.length < cnt) { @@ -41,34 +59,34 @@ export class BytesIter { this.bytes = this.bytes.slice(cnt) - return BigInt(add0x(bytes)) + return this.ResultType(add0x(bytes)) } - public nextUint8(): bigint { + public nextUint8(): T { return this.nextByte() } - public nextUint16(): bigint { + public nextUint16(): T { return this.nextBytes(2) } - public nextUint24(): bigint { + public nextUint24(): T { return this.nextBytes(3) } - public nextUint32(): bigint { + public nextUint32(): T { return this.nextBytes(4) } - public nextUint128(): bigint { + public nextUint128(): T { return this.nextBytes(16) } - public nextUint160(): bigint { + public nextUint160(): T { return this.nextBytes(20) } - public nextUint256(): bigint { + public nextUint256(): T { return this.nextBytes(32) } } diff --git a/src/utils/as-bytes.ts b/src/utils/as-bytes.ts new file mode 100644 index 0000000..399ad7c --- /dev/null +++ b/src/utils/as-bytes.ts @@ -0,0 +1,13 @@ +/** + * Formats `val` as 0x prefixed string with even length + * @param val + */ +export function asBytes(val: bigint): string { + const hex = val.toString(16) + + if (hex.length % 2) { + return '0x0' + hex + } + + return '0x' + hex +} diff --git a/src/utils/get-bytes-count.ts b/src/utils/get-bytes-count.ts new file mode 100644 index 0000000..85a3eaa --- /dev/null +++ b/src/utils/get-bytes-count.ts @@ -0,0 +1,5 @@ +import {trim0x} from './zero-x-prefix' + +export function getBytesCount(hex: string): bigint { + return BigInt(trim0x(hex).length / 2) +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 1d5c1a6..9ee045a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1 +1,3 @@ export * from './zero-x-prefix' +export * from './get-bytes-count' +export * from './as-bytes'