github.com/protolambda/zssz@v0.1.5/types/ssz_ptr.go (about)

     1  package types
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	. "github.com/protolambda/zssz/dec"
     7  	. "github.com/protolambda/zssz/enc"
     8  	. "github.com/protolambda/zssz/htr"
     9  	. "github.com/protolambda/zssz/pretty"
    10  	"github.com/protolambda/zssz/util/ptrutil"
    11  	"reflect"
    12  	"unsafe"
    13  )
    14  
    15  // proxies SSZ behavior to the SSZ type of the object being pointed to.
    16  type SSZPtr struct {
    17  	elemSSZ SSZ
    18  	alloc   ptrutil.AllocationFn
    19  }
    20  
    21  func NewSSZPtr(factory SSZFactoryFn, typ reflect.Type) (*SSZPtr, error) {
    22  	if typ.Kind() != reflect.Ptr {
    23  		return nil, fmt.Errorf("typ is not a pointer")
    24  	}
    25  	elemTyp := typ.Elem()
    26  	elemSSZ, err := factory(elemTyp)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  	alloc := func(p unsafe.Pointer) unsafe.Pointer {
    31  		return ptrutil.AllocateSpace(p, elemTyp)
    32  	}
    33  	return &SSZPtr{elemSSZ: elemSSZ, alloc: alloc}, nil
    34  }
    35  
    36  func (v *SSZPtr) FuzzMinLen() uint64 {
    37  	return v.elemSSZ.FuzzMinLen()
    38  }
    39  
    40  func (v *SSZPtr) FuzzMaxLen() uint64 {
    41  	return v.elemSSZ.FuzzMaxLen()
    42  }
    43  
    44  func (v *SSZPtr) MinLen() uint64 {
    45  	return v.elemSSZ.MinLen()
    46  }
    47  
    48  func (v *SSZPtr) MaxLen() uint64 {
    49  	return v.elemSSZ.MaxLen()
    50  }
    51  
    52  func (v *SSZPtr) FixedLen() uint64 {
    53  	return v.elemSSZ.FixedLen()
    54  }
    55  
    56  func (v *SSZPtr) IsFixed() bool {
    57  	return v.elemSSZ.IsFixed()
    58  }
    59  
    60  func (v *SSZPtr) SizeOf(p unsafe.Pointer) uint64 {
    61  	innerPtr := unsafe.Pointer(*(*uintptr)(p))
    62  	return v.elemSSZ.SizeOf(innerPtr)
    63  }
    64  
    65  func (v *SSZPtr) Encode(eb *EncodingWriter, p unsafe.Pointer) error {
    66  	innerPtr := unsafe.Pointer(*(*uintptr)(p))
    67  	return v.elemSSZ.Encode(eb, innerPtr)
    68  }
    69  
    70  func (v *SSZPtr) Decode(dr *DecodingReader, p unsafe.Pointer) error {
    71  	if p == unsafe.Pointer(nil) {
    72  		return errors.New("cannot decode into nil pointer")
    73  	}
    74  	if *(*uintptr)(p) == uintptr(0) {
    75  		contentsPtr := v.alloc(p)
    76  		return v.elemSSZ.Decode(dr, contentsPtr)
    77  	} else {
    78  		return v.elemSSZ.Decode(dr, unsafe.Pointer(*(*uintptr)(p)))
    79  	}
    80  }
    81  
    82  func (v *SSZPtr) DryCheck(dr *DecodingReader) error {
    83  	return v.elemSSZ.DryCheck(dr)
    84  }
    85  
    86  func (v *SSZPtr) HashTreeRoot(h MerkleFn, p unsafe.Pointer) [32]byte {
    87  	innerPtr := unsafe.Pointer(*(*uintptr)(p))
    88  	return v.elemSSZ.HashTreeRoot(h, innerPtr)
    89  }
    90  
    91  func (v *SSZPtr) Pretty(indent uint32, w *PrettyWriter, p unsafe.Pointer) {
    92  	innerPtr := unsafe.Pointer(*(*uintptr)(p))
    93  	if innerPtr == nil {
    94  		w.WriteIndent(indent)
    95  		w.Write("null")
    96  	} else {
    97  		v.elemSSZ.Pretty(indent, w, innerPtr)
    98  	}
    99  }