Skip to content

Commit

Permalink
feat: add sliceFrom to ListCompositeTreeViewDU (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
ensi321 authored Apr 19, 2024
1 parent 3cc1529 commit b3fa4f1
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
43 changes: 42 additions & 1 deletion packages/ssz/src/viewDU/listComposite.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Node, treeZeroAfterIndex} from "@chainsafe/persistent-merkle-tree";
import {Node, subtreeFillToContents, treeZeroAfterIndex, zeroNode} from "@chainsafe/persistent-merkle-tree";
import {ByteViews, ValueOf} from "../type/abstract";
import {CompositeType, CompositeView, CompositeViewDU} from "../type/composite";
import {ListCompositeType} from "../view/listComposite";
Expand Down Expand Up @@ -66,6 +66,47 @@ export class ListCompositeTreeViewDU<
return this.type.getViewDU(newRootNode) as this;
}

/**
* Returns a new ListCompositeTreeViewDU instance with the values from `index` to the end of list
*
* ```ts
* const nodes = getChunkNodes()
* return listFromChunkNodes(node.slice(index))
* ```
*
* Note: If index === n, returns an empty list of length 0
*
*/
sliceFrom(index: number): this {
// Commit before getting rootNode to ensure all pending data is in the rootNode
this.commit();

// If negative index, try to make it positive long as |index| < length
if (index < 0) {
index += this.nodes.length;
}
// If slicing from 0 or neg index, no slicing is necesary
if (index <= 0) {
return this;
}

let newChunksNode;
let newLength;

if (index >= this.nodes.length) {
newChunksNode = zeroNode(this.type.chunkDepth);
newLength = 0;
} else {
const nodes = this.nodes.slice(index);
newChunksNode = subtreeFillToContents(nodes, this.type.chunkDepth);
newLength = nodes.length;
}

const newRootNode = this.type.tree_setChunksNode(this._rootNode, newChunksNode, newLength);

return this.type.getViewDU(newRootNode) as this;
}

/**
* Same method to `type/listComposite.ts` leveraging cached nodes.
*/
Expand Down
19 changes: 19 additions & 0 deletions packages/ssz/test/unit/byType/listComposite/tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,22 @@ describe("ListCompositeType.sliceTo", () => {
}
});
});

describe("ListCompositeType.sliceFrom", () => {
it("Slice List from multiple length", () => {
const listType = new ListCompositeType(ssz.Root, 1024);
const listLength = 16;
const list = Array.from({length: listLength}, (_, i) => Buffer.alloc(32, i));
const listView = listType.toViewDU(list);

for (let i = -(listLength + 1); i < listLength + 1; i++) {
// compare list.slice(i) to listView.sliceFrom(i), they should be equivalent
const slicedList = list.slice(i);
const slicedListView = listView.sliceFrom(i);

expect(slicedListView.length).to.equal(slicedList.length);
expect(toHexString(slicedListView.serialize())).to.equal(toHexString(listType.serialize(slicedList)));
expect(toHexString(slicedListView.hashTreeRoot())).to.equal(toHexString(listType.hashTreeRoot(slicedList)));
}
});
});

0 comments on commit b3fa4f1

Please sign in to comment.