@aggris2/ssz
Version:
Simple Serialize
100 lines • 4.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArrayType = void 0;
const persistent_merkle_tree_1 = require("@chainsafe/persistent-merkle-tree");
const composite_1 = require("./composite");
const arrayBasic_1 = require("./arrayBasic");
/* eslint-disable @typescript-eslint/member-ordering */
/**
* Array: ordered homogeneous collection
*/
class ArrayType extends composite_1.CompositeType {
constructor(elementType) {
super();
this.elementType = elementType;
}
defaultValue() {
return arrayBasic_1.value_defaultValueArray(this.elementType, this.defaultLen);
}
// Proofs
getPropertyType() {
return this.elementType;
}
getPropertyGindex(prop) {
if (typeof prop !== "number") {
throw Error(`Invalid array index: ${prop}`);
}
const chunkIdx = Math.floor(prop / this.itemsPerChunk);
return persistent_merkle_tree_1.toGindex(this.depth, BigInt(chunkIdx));
}
getIndexProperty(index) {
return index;
}
tree_getLeafGindices(rootGindex, rootNode) {
let length;
if (this.isList) {
if (!rootNode) {
throw new Error("List type requires tree argument to get leaves");
}
length = this.tree_getLength(rootNode);
}
else {
// Vectors don't need a rootNode to return length
length = this.tree_getLength(null);
}
const gindices = [];
if (composite_1.isCompositeType(this.elementType)) {
// Underlying elements exist one per chunk
// Iterate through chunk gindices, recursively fetching leaf gindices from each chunk
const startIndex = persistent_merkle_tree_1.toGindex(this.depth, BigInt(0));
const endGindex = startIndex + BigInt(length);
const extendedStartIndex = persistent_merkle_tree_1.concatGindices([rootGindex, startIndex]);
if (this.elementType.fixedSize === null) {
if (!rootNode) {
/* istanbul ignore next - unreachable code */
throw new Error("Array of variable size requires tree argument to get leaves");
}
// variable-length elements must pass the underlying subtrees to determine the length
for (let gindex = startIndex, extendedGindex = extendedStartIndex; gindex < endGindex; gindex++, extendedGindex++) {
gindices.push(...this.elementType.tree_getLeafGindices(extendedGindex, persistent_merkle_tree_1.getNode(rootNode, gindex)));
}
}
else {
for (let i = 0, extendedGindex = extendedStartIndex; i < length; i++, extendedGindex++) {
gindices.push(...this.elementType.tree_getLeafGindices(extendedGindex));
}
}
}
// Basic
else {
const chunkCount = Math.ceil(length / this.itemsPerChunk);
const startIndex = persistent_merkle_tree_1.concatGindices([rootGindex, persistent_merkle_tree_1.toGindex(this.depth, BigInt(0))]);
const endGindex = startIndex + BigInt(chunkCount);
for (let gindex = startIndex; gindex < endGindex; gindex++) {
gindices.push(gindex);
}
}
// include the length chunk
if (this.isList) {
gindices.push(persistent_merkle_tree_1.concatGindices([rootGindex, composite_1.LENGTH_GINDEX]));
}
return gindices;
}
// JSON
fromJson(json) {
// TODO: Do a better typesafe approach, all final classes of ArrayType implement ArrayProps
// There are multiple tests that cover this path for all clases
return arrayBasic_1.value_fromJsonArray(this.elementType, json, this);
}
toJson(value) {
return arrayBasic_1.value_toJsonArray(this.elementType, value, this);
}
clone(value) {
return arrayBasic_1.value_cloneArray(this.elementType, value);
}
equals(a, b) {
return arrayBasic_1.value_equals(this.elementType, a, b);
}
}
exports.ArrayType = ArrayType;
//# sourceMappingURL=array.js.map