@chainsafe/ssz
Version:
Simple Serialize
81 lines • 3.48 kB
JavaScript
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