github.com/protolambda/zssz@v0.1.5/types/ssz_bitvector.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "github.com/protolambda/zssz/bitfields" 6 . "github.com/protolambda/zssz/dec" 7 . "github.com/protolambda/zssz/enc" 8 . "github.com/protolambda/zssz/htr" 9 "github.com/protolambda/zssz/merkle" 10 . "github.com/protolambda/zssz/pretty" 11 "github.com/protolambda/zssz/util/ptrutil" 12 "reflect" 13 "unsafe" 14 ) 15 16 type SSZBitvector struct { 17 bitLen uint64 18 byteLen uint64 19 } 20 21 var bitvectorMeta = reflect.TypeOf((*bitfields.BitvectorMeta)(nil)).Elem() 22 23 func NewSSZBitvector(typ reflect.Type) (*SSZBitvector, error) { 24 if typ.Kind() != reflect.Array { 25 return nil, fmt.Errorf("typ is not a fixed-length bytes array (bitvector requirement)") 26 } 27 if typ.Elem().Kind() != reflect.Uint8 { 28 return nil, fmt.Errorf("typ is not a bytes array (bitvector requirement)") 29 } 30 ptrTyp := reflect.PtrTo(typ) 31 if !ptrTyp.Implements(bitvectorMeta) { 32 return nil, fmt.Errorf("*typ (pointer type) is not a bitvector") 33 } 34 typedNil := reflect.New(ptrTyp).Elem().Interface().(bitfields.BitvectorMeta) 35 bitLen := typedNil.BitLen() 36 byteLen := uint64(typ.Len()) 37 if (bitLen+7)>>3 != byteLen { 38 return nil, fmt.Errorf("bitvector type has not the expected %d bytes to cover %d bits", byteLen, bitLen) 39 } 40 res := &SSZBitvector{bitLen: bitLen, byteLen: byteLen} 41 return res, nil 42 } 43 44 // in bytes (rounded up), not bits 45 func (v *SSZBitvector) FuzzMinLen() uint64 { 46 return v.byteLen 47 } 48 49 // in bytes (rounded up), not bits 50 func (v *SSZBitvector) FuzzMaxLen() uint64 { 51 return v.byteLen 52 } 53 54 // in bytes (rounded up), not bits 55 func (v *SSZBitvector) MinLen() uint64 { 56 return v.byteLen 57 } 58 59 // in bytes (rounded up), not bits 60 func (v *SSZBitvector) MaxLen() uint64 { 61 return v.byteLen 62 } 63 64 // in bytes (rounded up), not bits 65 func (v *SSZBitvector) FixedLen() uint64 { 66 return v.byteLen 67 } 68 69 func (v *SSZBitvector) IsFixed() bool { 70 return true 71 } 72 73 func (v *SSZBitvector) SizeOf(p unsafe.Pointer) uint64 { 74 return v.byteLen 75 } 76 77 func (v *SSZBitvector) Encode(eb *EncodingWriter, p unsafe.Pointer) error { 78 sh := ptrutil.GetSliceHeader(p, v.byteLen) 79 data := *(*[]byte)(unsafe.Pointer(sh)) 80 return eb.Write(data) 81 } 82 83 func (v *SSZBitvector) Decode(dr *DecodingReader, p unsafe.Pointer) error { 84 sh := ptrutil.GetSliceHeader(p, v.byteLen) 85 data := *(*[]byte)(unsafe.Pointer(sh)) 86 if _, err := dr.Read(data); err != nil { 87 return err 88 } 89 // check if the data is a valid bitvector value (0 bits for unused bits) 90 return bitfields.BitvectorCheck(data, v.bitLen) 91 } 92 93 func (v *SSZBitvector) DryCheck(dr *DecodingReader) error { 94 if v.bitLen == 0 { 95 return nil 96 } 97 if v.byteLen > 1 { 98 _, err := dr.Skip(v.byteLen - 1) 99 if err != nil { 100 return err 101 } 102 } 103 last, err := dr.ReadByte() 104 if err != nil { 105 return err 106 } 107 return bitfields.BitvectorCheckLastByte(last, v.bitLen) 108 } 109 110 func (v *SSZBitvector) HashTreeRoot(h MerkleFn, p unsafe.Pointer) [32]byte { 111 sh := ptrutil.GetSliceHeader(p, v.byteLen) 112 data := *(*[]byte)(unsafe.Pointer(sh)) 113 leafCount := (v.byteLen + 31) >> 5 114 leaf := func(i uint64) []byte { 115 s := i << 5 116 e := (i + 1) << 5 117 // pad the data 118 if e > v.byteLen { 119 x := [32]byte{} 120 copy(x[:], data[s:v.byteLen]) 121 return x[:] 122 } 123 return data[s:e] 124 } 125 return merkle.Merkleize(h, leafCount, leafCount, leaf) 126 } 127 128 func (v *SSZBitvector) Pretty(indent uint32, w *PrettyWriter, p unsafe.Pointer) { 129 w.WriteIndent(indent) 130 sh := ptrutil.GetSliceHeader(p, v.byteLen) 131 data := *(*[]byte)(unsafe.Pointer(sh)) 132 w.Write(fmt.Sprintf("%08b", data)) 133 }