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  }