github.com/protolambda/zssz@v0.1.5/types/ssz_vector_basic.go (about) 1 package types 2 3 import ( 4 "fmt" 5 . "github.com/protolambda/zssz/dec" 6 . "github.com/protolambda/zssz/enc" 7 . "github.com/protolambda/zssz/htr" 8 . "github.com/protolambda/zssz/pretty" 9 "github.com/protolambda/zssz/util/endianness" 10 "reflect" 11 "unsafe" 12 ) 13 14 type SSZBasicVector struct { 15 elemKind reflect.Kind 16 elemSSZ SSZ 17 length uint64 18 byteLen uint64 19 } 20 21 func NewSSZBasicVector(typ reflect.Type) (*SSZBasicVector, error) { 22 if typ.Kind() != reflect.Array { 23 return nil, fmt.Errorf("typ is not a fixed-length array") 24 } 25 elemTyp := typ.Elem() 26 elemKind := elemTyp.Kind() 27 elemSSZ, err := GetBasicSSZElemType(elemKind) 28 if err != nil { 29 return nil, err 30 } 31 if elemSSZ.FixedLen() != uint64(elemTyp.Size()) { 32 return nil, fmt.Errorf("basic element type has different size than SSZ type unexpectedly, ssz: %d, go: %d", elemSSZ.FixedLen(), elemTyp.Size()) 33 } 34 length := uint64(typ.Len()) 35 36 res := &SSZBasicVector{ 37 elemKind: elemKind, 38 elemSSZ: elemSSZ, 39 length: length, 40 byteLen: length * elemSSZ.FixedLen(), 41 } 42 return res, nil 43 } 44 45 func (v *SSZBasicVector) FuzzMinLen() uint64 { 46 return v.byteLen 47 } 48 49 func (v *SSZBasicVector) FuzzMaxLen() uint64 { 50 return v.byteLen 51 } 52 53 func (v *SSZBasicVector) MinLen() uint64 { 54 return v.byteLen 55 } 56 57 func (v *SSZBasicVector) MaxLen() uint64 { 58 return v.byteLen 59 } 60 61 func (v *SSZBasicVector) FixedLen() uint64 { 62 return v.byteLen 63 } 64 65 func (v *SSZBasicVector) IsFixed() bool { 66 return true 67 } 68 69 func (v *SSZBasicVector) SizeOf(p unsafe.Pointer) uint64 { 70 return v.byteLen 71 } 72 73 func (v *SSZBasicVector) Encode(eb *EncodingWriter, p unsafe.Pointer) error { 74 // we can just write the data as-is in a few contexts: 75 // - if we're in a little endian architecture 76 // - if there is no endianness to deal with 77 if endianness.IsLittleEndian || v.elemSSZ.FixedLen() == 1 { 78 return LittleEndianBasicSeriesEncode(eb, p, v.byteLen) 79 } else { 80 return EncodeFixedSeries(v.elemSSZ.Encode, v.length, uintptr(v.elemSSZ.FixedLen()), eb, p) 81 } 82 } 83 84 func (v *SSZBasicVector) Decode(dr *DecodingReader, p unsafe.Pointer) error { 85 if endianness.IsLittleEndian || v.elemSSZ.FixedLen() == 1 { 86 return LittleEndianBasicSeriesDecode(dr, p, v.byteLen, v.byteLen, v.elemKind == reflect.Bool) 87 } else { 88 return DecodeFixedSeries(v.elemSSZ.Decode, v.byteLen, uintptr(v.elemSSZ.FixedLen()), dr, p) 89 } 90 } 91 92 func (v *SSZBasicVector) DryCheck(dr *DecodingReader) error { 93 return BasicSeriesDryCheck(dr, v.byteLen, v.byteLen, v.elemKind == reflect.Bool) 94 } 95 96 func (v *SSZBasicVector) HashTreeRoot(h MerkleFn, p unsafe.Pointer) [32]byte { 97 if endianness.IsLittleEndian || v.elemSSZ.FixedLen() == 1 { 98 return LittleEndianBasicSeriesHTR(h, p, v.byteLen, v.byteLen) 99 } else { 100 return BigEndianBasicSeriesHTR(h, p, v.byteLen, v.byteLen, uint8(v.elemSSZ.FixedLen())) 101 } 102 } 103 104 func (v *SSZBasicVector) Pretty(indent uint32, w *PrettyWriter, p unsafe.Pointer) { 105 w.WriteIndent(indent) 106 w.Write("[\n") 107 w.WriteIndent(indent + 1) 108 CallSeries(func(i uint64, p unsafe.Pointer) { 109 v.elemSSZ.Pretty(0, w, p) 110 if i == v.length-1 { 111 w.Write("\n") 112 } else if i%(32/v.elemSSZ.FixedLen()) == 0 { 113 w.Write(",\n") 114 w.WriteIndent(indent + 1) 115 } else { 116 w.Write(", ") 117 } 118 }, v.length, uintptr(v.elemSSZ.FixedLen()), p) 119 w.WriteIndent(indent) 120 w.Write("]") 121 }