UNPKG

@chainsafe/ssz

Version:

Simple Serialize

149 lines 6.37 kB
import { getNodesAtDepth, subtreeFillToContents, zeroNode } from "@chainsafe/persistent-merkle-tree"; import { zeroSnapshot } from "../util/snapshot.js"; import { ListCompositeTreeViewDU } from "./listComposite.js"; /** * Similar to ListCompositeTreeViewDU but this is created from a snapshot so some methods are not supported * for some specific index ranges. * Note that the backed tree is not a full tree, but a partial tree created from a snapshot. */ export class PartialListCompositeTreeViewDU extends ListCompositeTreeViewDU { type; _rootNode; snapshot; constructor(type, _rootNode, snapshot, cache) { super(type, _rootNode, cache); this.type = type; this._rootNode = _rootNode; this.snapshot = snapshot; } /** * Create snapshot from the first `count` elements of the list. */ toSnapshot(count) { if (count < this.snapshot.count) { throw new Error(`Cannot create snapshot with count ${count} less than existing snapshot count ${this.snapshot.count}`); } return super.toSnapshot(count); } /** Methods in ArrayCompositeTreeViewDU */ get(index) { if (index < this.snapshot.count) { throw new Error(`Cannot get index ${index} less than existing snapshot count ${this.snapshot.count}`); } return super.get(index); } getReadonly(index) { if (index < this.snapshot.count) { throw new Error(`Cannot get index ${index} less than existing snapshot count ${this.snapshot.count}`); } return super.getReadonly(index); } set(index, view) { if (index < this.snapshot.count) { throw new Error(`Cannot set index ${index} less than existing snapshot count ${this.snapshot.count}`); } super.set(index, view); } getAllReadonly() { throw new Error("getAllReadonly() is not supported for PartialListCompositeTreeViewDU"); } getAllReadonlyValues() { throw new Error("getAllReadonlyValues() is not supported for PartialListCompositeTreeViewDU"); } // commit() is inherited from ArrayCompositeTreeViewDU /** Methods in ListCompositeTreeViewDU */ // push() is inherited from ListCompositeTreeViewDU /** * Similar to ListCompositeTreeViewDU.sliceTo() but: * - throw error if index < snapshot.count - 1 * - special handle for index === snapshot.count - 1, we restore from snapshot */ sliceTo(index) { if (index < this.snapshot.count - 1) { throw new Error(`Cannot slice to index ${index} less than existing snapshot count - 1 ${this.snapshot.count - 1}`); } this.commit(); if (index === this.snapshot.count - 1) { // super.sliceTo() uses treeZeroAfterIndex() which does not work well in this case // this is because treeZeroAfterIndex() requires navigating the tree to index first which we don't have in this case return this.type.toPartialViewDU(this.snapshot); } return super.sliceTo(index); } /** * Similar to ListCompositeTreeViewDU.sliceFrom() but here we cannot call `populateAllNodes()` to get all nodes * Use getNodesAtDepth() instead */ sliceFrom(index) { if (index < this.snapshot.count - 1) { throw new Error(`Cannot slice to index ${index} less than existing snapshot count ${this.snapshot.count - 1}`); } // Commit before getting rootNode to ensure all pending data is in the rootNode this.commit(); let newChunksNode; let newLength; if (index >= this.length) { newChunksNode = zeroNode(this.type.chunkDepth); newLength = 0; } else { const nodeCount = this.length - index; const nodes = getNodesAtDepth(this._rootNode, this.type.depth, index, nodeCount); newChunksNode = subtreeFillToContents(nodes, this.type.chunkDepth); newLength = nodes.length; } const newRootNode = this.type.tree_setChunksNode(this._rootNode, newChunksNode, newLength); // Use zeroSnapshot because this is equivalent to a full tree return new PartialListCompositeTreeViewDU(this.type, newRootNode, zeroSnapshot(this.type.chunkDepth)); } serializeToBytes() { throw new Error("serializeToBytes() is not supported for PartialListCompositeTreeViewDU"); } /** Methods in TreeViewDU */ // hashTreeRoot() is inherited from TreeViewDU // batchHashTreeRoot() is inherited from TreeViewDU /** * Does not support serialize and deserialize, it works through snapshot. */ serialize() { throw new Error("serialize() is not supported for PartialListCompositeTreeViewDU"); } /** * Clone using rootNodeToViewDU() instead of getViewDU(). */ clone(dontTransferCache) { if (dontTransferCache) return this.rootNodeToViewDU(this.node); const cache = this.cache; this.clearCache(); return this.rootNodeToViewDU(this.node, cache); } /** * Mainly used for testing, to ensure the snapshot is correct. * Set undefined values for items 0 to snapshot.count - 1 */ toValue() { const values = new Array(this.length); const snapshotCount = this.snapshot.count; const allNodes = getNodesAtDepth(this._rootNode, this.type.depth, snapshotCount, this.length - snapshotCount); const type = this.type.elementType; // value of 0 to snapshot.count - 1 is from snapshot, and they are undefined for (let i = snapshotCount; i < this.length; i++) { values[i] = type.toValueFromViewDU(type.getViewDU(allNodes[i - snapshotCount])); } return values; } /** * Throw error because we only have partial tree in this case. */ populateAllNodes() { throw new Error("populateAllNodes() is not supported for PartialListCompositeTreeViewDU"); } /** * Since this.type.getViewDU() is not supported for this type, create a new PartialListCompositeTreeViewDU instead. */ rootNodeToViewDU(rootNode, cache) { return new PartialListCompositeTreeViewDU(this.type, rootNode, this.snapshot, cache); } } //# sourceMappingURL=partialListComposite.js.map