Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 1x 1006x 695x 311x 178x 133x 752x 752x 887x 135x 887x 3165x 752x 752x 695x 695x 2896x 4x 4x 4x 57x 57x 57x 269x 57x 1x 1x 1x 83x 83x 83x 1x 340x 340x 340x 78x 78x 262x 4x 4x 4x 340x | import { ABIField, ABISerializableConstructor, ABISerializableObject, ABITypeModifiers, } from '../serializer/serializable' import {abiDecode, Resolved} from '../serializer/decoder' import {abiEncode} from '../serializer/encoder' import {isInstanceOf} from '../utils' export interface StructConstructor extends ABISerializableConstructor { new <T extends Struct>(...args: any[]): T structFields: ABIField[] } export class Struct implements ABISerializableObject { static abiName = '__struct' static abiFields: ABIField[] static abiBase: ABISerializableConstructor static from<T extends StructConstructor>(this: T, value: any): InstanceType<T> static from(value: any): unknown static from(value: any) { if (value[Resolved] === true) { // objects already resolved return new this(value) } if (isInstanceOf(value, this)) { return value } return abiDecode({object: value, type: this}) } static get structFields() { const rv: ABIField[] = [] const walk = (t: ABISerializableConstructor) => { if (t.abiBase) { walk(t.abiBase) } for (const field of t.abiFields || []) { rv.push(field) } } walk(this) return rv } /** @internal */ constructor(object: any) { const self = this.constructor as typeof Struct for (const field of self.structFields) { this[field.name] = object[field.name] } } /** * Return true if this struct equals the other. * * Note: This compares the ABI encoded bytes of both structs, subclasses * should implement their own fast equality check when possible. */ equals(other: any): boolean { const self = this.constructor as typeof Struct Iif ( other.constructor && typeof other.constructor.abiName === 'string' && other.constructor.abiName !== self.abiName ) { return false } return abiEncode({object: this}).equals(abiEncode({object: self.from(other) as any})) } /** @internal */ toJSON() { const self = this.constructor as typeof Struct const rv: any = {} for (const field of self.structFields) { rv[field.name] = this[field.name] } return rv } } export namespace Struct { const FieldsOwner = Symbol('FieldsOwner') export function type(name: string) { return function <T extends StructConstructor>(struct: T) { struct.abiName = name return struct } } export function field( type: ABISerializableConstructor | string, options: ABITypeModifiers = {} ) { return <T extends Struct>(target: T, name: string) => { const ctor = target.constructor as StructConstructor if (!ctor.abiFields) { ctor.abiFields = [] ctor.abiFields[FieldsOwner] = ctor } else if (ctor.abiFields[FieldsOwner] !== ctor) { // if the target class isn't the owner we set the base and start new fields ctor.abiBase = ctor.abiFields[FieldsOwner] ctor.abiFields = [] ctor.abiFields[FieldsOwner] = ctor } ctor.abiFields.push({...options, name, type}) } } } |