UNPKG

@chainsafe/ssz

Version:

Simple Serialize

81 lines 3.48 kB
import { getNodesAtDepth } from "@chainsafe/persistent-merkle-tree"; import { TreeView } from "./abstract.js"; export class ArrayBasicTreeView extends TreeView { type; tree; constructor(type, tree) { super(); this.type = type; this.tree = tree; } /** * Number of elements in the array. Equal to the Uint32 value of the Tree's length node */ get length() { return this.type.tree_getLength(this.tree.rootNode); } get node() { return this.tree.rootNode; } /** * Get element at `index`. Returns the Basic element type value directly */ get(index) { // First walk through the tree to get the root node for that index const chunkIndex = Math.floor(index / this.type.itemsPerChunk); const leafNode = this.tree.getNodeAtDepth(this.type.depth, chunkIndex); return this.type.elementType.tree_getFromPackedNode(leafNode, index); } /** * Set Basic element type `value` at `index` */ set(index, value) { const length = this.length; if (index >= length) { throw Error(`Error setting index over length ${index} > ${length}`); } const chunkIndex = Math.floor(index / this.type.itemsPerChunk); const leafNodePrev = this.tree.getNodeAtDepth(this.type.depth, chunkIndex); // Create a new node to preserve immutability const leafNode = leafNodePrev.clone(); this.type.elementType.tree_setToPackedNode(leafNode, index, value); // Commit immediately this.tree.setNodeAtDepth(this.type.depth, chunkIndex, leafNode); } /** * Get all values of this array as Basic element type values, from index zero to `this.length - 1` * @param values optional output parameter, if is provided it must be an array of the same length as this array */ getAll(values) { if (values && values.length !== this.length) { throw Error(`Expected ${this.length} values, got ${values.length}`); } const length = this.length; const chunksNode = this.type.tree_getChunksNode(this.node); const chunkCount = Math.ceil(length / this.type.itemsPerChunk); const leafNodes = getNodesAtDepth(chunksNode, this.type.chunkDepth, 0, chunkCount); values = values ?? new Array(length); const itemsPerChunk = this.type.itemsPerChunk; // Prevent many access in for loop below const lenFullNodes = Math.floor(length / itemsPerChunk); const remainder = length % itemsPerChunk; for (let n = 0; n < lenFullNodes; n++) { const leafNode = leafNodes[n]; // TODO: Implement add a fast bulk packed element reader in the elementType // ``` // abstract getValuesFromPackedNode(leafNode: LeafNode, output: V[], indexOffset: number): void; // ``` // if performance here is a problem for (let i = 0; i < itemsPerChunk; i++) { values[n * itemsPerChunk + i] = this.type.elementType.tree_getFromPackedNode(leafNode, i); } } if (remainder > 0) { const leafNode = leafNodes[lenFullNodes]; for (let i = 0; i < remainder; i++) { values[lenFullNodes * itemsPerChunk + i] = this.type.elementType.tree_getFromPackedNode(leafNode, i); } } return values; } } //# sourceMappingURL=arrayBasic.js.map