From 8f73f53c95d8ba887558863b8b726a2b3f5b7e2b Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 25 Nov 2018 20:05:41 -0800 Subject: Moved calldata iterator logic into its own iterator clas --- .../utils/src/abi_encoder/calldata/iterator.ts | 94 ++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 packages/utils/src/abi_encoder/calldata/iterator.ts (limited to 'packages/utils/src/abi_encoder/calldata/iterator.ts') diff --git a/packages/utils/src/abi_encoder/calldata/iterator.ts b/packages/utils/src/abi_encoder/calldata/iterator.ts new file mode 100644 index 000000000..3e3367e10 --- /dev/null +++ b/packages/utils/src/abi_encoder/calldata/iterator.ts @@ -0,0 +1,94 @@ +/* tslint:disable max-classes-per-file */ +import * as _ from 'lodash'; + +import { Queue } from '../utils/queue'; + +import * as CalldataBlocks from './blocks'; +import { CalldataBlock } from './calldata_block'; + +/** + * Iterator class for Calldata Blocks. Blocks follows the order + * they should be put into calldata that is passed to he EVM. + * + * Example #1: + * Let root = Set { + * Blob{} A, + * Pointer { + * Blob{} a + * } B, + * Blob{} C + * } + * It will iterate as follows: [A, B, C, B.a] + * + * Example #2: + * Let root = Set { + * Blob{} A, + * Pointer { + * Blob{} a + * Pointer { + * Blob{} b + * } + * } B, + * Pointer { + * Blob{} c + * } C + * } + * It will iterate as follows: [A, B, C, B.a, B.b, C.c] + */ +abstract class BaseIterator { + protected readonly _root: CalldataBlock; + protected readonly _queue: Queue; + + private static _createQueue(block: CalldataBlock): Queue { + const queue = new Queue(); + // Base case + if (!(block instanceof CalldataBlocks.Set)) { + queue.pushBack(block); + return queue; + } + // This is a set; add members + const set = block; + _.eachRight(set.getMembers(), (member: CalldataBlock) => { + queue.mergeFront(BaseIterator._createQueue(member)); + }); + // Add children + _.each(set.getMembers(), (member: CalldataBlock) => { + // Traverse child if it is a unique pointer. + // A pointer that is an alias for another pointer is ignored. + if (member instanceof CalldataBlocks.Pointer && member.getAlias() === undefined) { + const dependency = member.getDependency(); + queue.mergeBack(BaseIterator._createQueue(dependency)); + } + }); + // Put set block at the front of the queue + queue.pushFront(set); + return queue; + } + + public constructor(root: CalldataBlock) { + this._root = root; + this._queue = BaseIterator._createQueue(root); + } + + public abstract next(): CalldataBlock | undefined; +} + +export class CalldataIterator extends BaseIterator { + public constructor(root: CalldataBlock) { + super(root); + } + + public next(): CalldataBlock | undefined { + return this._queue.popFront(); + } +} + +export class ReverseCalldataIterator extends BaseIterator { + public constructor(root: CalldataBlock) { + super(root); + } + + public next(): CalldataBlock | undefined { + return this._queue.popBack(); + } +} -- cgit v1.2.3 From bab1c92c703ee53e77a56a7f7a5e3bba5b4a2306 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Sun, 25 Nov 2018 20:11:10 -0800 Subject: Linter for Calldata Block Iterator --- .../utils/src/abi_encoder/calldata/iterator.ts | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'packages/utils/src/abi_encoder/calldata/iterator.ts') diff --git a/packages/utils/src/abi_encoder/calldata/iterator.ts b/packages/utils/src/abi_encoder/calldata/iterator.ts index 3e3367e10..8e2b16a5a 100644 --- a/packages/utils/src/abi_encoder/calldata/iterator.ts +++ b/packages/utils/src/abi_encoder/calldata/iterator.ts @@ -35,7 +35,7 @@ import { CalldataBlock } from './calldata_block'; * } * It will iterate as follows: [A, B, C, B.a, B.b, C.c] */ -abstract class BaseIterator { +abstract class BaseIterator implements Iterable { protected readonly _root: CalldataBlock; protected readonly _queue: Queue; @@ -70,7 +70,25 @@ abstract class BaseIterator { this._queue = BaseIterator._createQueue(root); } - public abstract next(): CalldataBlock | undefined; + public [Symbol.iterator](): { next: () => IteratorResult } { + return { + next: () => { + const nextBlock = this.nextBlock(); + if (nextBlock !== undefined) { + return { + value: nextBlock, + done: false, + }; + } + return { + done: true, + value: new CalldataBlocks.Blob('', '', '', new Buffer('')), + }; + }, + }; + } + + public abstract nextBlock(): CalldataBlock | undefined; } export class CalldataIterator extends BaseIterator { @@ -78,7 +96,7 @@ export class CalldataIterator extends BaseIterator { super(root); } - public next(): CalldataBlock | undefined { + public nextBlock(): CalldataBlock | undefined { return this._queue.popFront(); } } @@ -88,7 +106,7 @@ export class ReverseCalldataIterator extends BaseIterator { super(root); } - public next(): CalldataBlock | undefined { + public nextBlock(): CalldataBlock | undefined { return this._queue.popBack(); } } -- cgit v1.2.3 From f31d4ddffd8dd97f2b2dc226f4f132d1c3192c76 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Tue, 27 Nov 2018 13:10:34 -0800 Subject: Replaced null/undefined checks with lodash --- packages/utils/src/abi_encoder/calldata/iterator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'packages/utils/src/abi_encoder/calldata/iterator.ts') diff --git a/packages/utils/src/abi_encoder/calldata/iterator.ts b/packages/utils/src/abi_encoder/calldata/iterator.ts index 8e2b16a5a..5307f7944 100644 --- a/packages/utils/src/abi_encoder/calldata/iterator.ts +++ b/packages/utils/src/abi_encoder/calldata/iterator.ts @@ -55,7 +55,7 @@ abstract class BaseIterator implements Iterable { _.each(set.getMembers(), (member: CalldataBlock) => { // Traverse child if it is a unique pointer. // A pointer that is an alias for another pointer is ignored. - if (member instanceof CalldataBlocks.Pointer && member.getAlias() === undefined) { + if (member instanceof CalldataBlocks.Pointer && _.isUndefined(member.getAlias())) { const dependency = member.getDependency(); queue.mergeBack(BaseIterator._createQueue(dependency)); } @@ -74,7 +74,7 @@ abstract class BaseIterator implements Iterable { return { next: () => { const nextBlock = this.nextBlock(); - if (nextBlock !== undefined) { + if (!_.isUndefined(nextBlock)) { return { value: nextBlock, done: false, -- cgit v1.2.3 From 2da7cadefa877ff824da8fbaecd59dbff5028728 Mon Sep 17 00:00:00 2001 From: Greg Hysen Date: Wed, 28 Nov 2018 13:47:01 -0800 Subject: Explicit imports for calldata --- packages/utils/src/abi_encoder/calldata/iterator.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'packages/utils/src/abi_encoder/calldata/iterator.ts') diff --git a/packages/utils/src/abi_encoder/calldata/iterator.ts b/packages/utils/src/abi_encoder/calldata/iterator.ts index 5307f7944..333b32b4f 100644 --- a/packages/utils/src/abi_encoder/calldata/iterator.ts +++ b/packages/utils/src/abi_encoder/calldata/iterator.ts @@ -3,7 +3,9 @@ import * as _ from 'lodash'; import { Queue } from '../utils/queue'; -import * as CalldataBlocks from './blocks'; +import { BlobCalldataBlock } from './blocks/blob'; +import { PointerCalldataBlock } from './blocks/pointer'; +import { SetCalldataBlock } from './blocks/set'; import { CalldataBlock } from './calldata_block'; /** @@ -42,7 +44,7 @@ abstract class BaseIterator implements Iterable { private static _createQueue(block: CalldataBlock): Queue { const queue = new Queue(); // Base case - if (!(block instanceof CalldataBlocks.Set)) { + if (!(block instanceof SetCalldataBlock)) { queue.pushBack(block); return queue; } @@ -55,7 +57,7 @@ abstract class BaseIterator implements Iterable { _.each(set.getMembers(), (member: CalldataBlock) => { // Traverse child if it is a unique pointer. // A pointer that is an alias for another pointer is ignored. - if (member instanceof CalldataBlocks.Pointer && _.isUndefined(member.getAlias())) { + if (member instanceof PointerCalldataBlock && _.isUndefined(member.getAlias())) { const dependency = member.getDependency(); queue.mergeBack(BaseIterator._createQueue(dependency)); } @@ -82,7 +84,7 @@ abstract class BaseIterator implements Iterable { } return { done: true, - value: new CalldataBlocks.Blob('', '', '', new Buffer('')), + value: new BlobCalldataBlock('', '', '', new Buffer('')), }; }, }; -- cgit v1.2.3