github.com/mavryk-network/mvgo@v1.19.9/contract/bind/or.go (about)

     1  package bind
     2  
     3  import (
     4  	"github.com/mavryk-network/mvgo/micheline"
     5  
     6  	"github.com/pkg/errors"
     7  )
     8  
     9  // Or is a type that can be either L or R.
    10  //
    11  // It maps to michelson's `or` type.
    12  type Or[L, R any] struct {
    13  	l       L
    14  	r       R
    15  	isRight bool
    16  }
    17  
    18  // Left returns a new Or[L, R] filled with the left value.
    19  func Left[L, R any](l L) Or[L, R] {
    20  	return Or[L, R]{l: l}
    21  }
    22  
    23  // Right returns a new Or[L, R] filled with the right value.
    24  func Right[L, R any](r R) Or[L, R] {
    25  	return Or[L, R]{r: r, isRight: true}
    26  }
    27  
    28  func (o Or[L, R]) IsLeft() bool {
    29  	return !o.isRight
    30  }
    31  
    32  func (o Or[L, R]) IsRight() bool {
    33  	return o.isRight
    34  }
    35  
    36  // Left returns the left value and true, if the Or is Left.
    37  func (o Or[L, R]) Left() (L, bool) {
    38  	return o.l, !o.isRight
    39  }
    40  
    41  // Right returns the right value and true, if the Or is Right.
    42  func (o Or[L, R]) Right() (R, bool) {
    43  	return o.r, o.isRight
    44  }
    45  
    46  func (o Or[L, R]) MarshalPrim(optimized bool) (micheline.Prim, error) {
    47  	if o.isRight {
    48  		inner, err := MarshalPrim(o.r, optimized)
    49  		if err != nil {
    50  			return micheline.Prim{}, err
    51  		}
    52  		return micheline.NewCode(micheline.D_RIGHT, inner), nil
    53  	} else {
    54  		inner, err := MarshalPrim(o.l, optimized)
    55  		if err != nil {
    56  			return micheline.Prim{}, err
    57  		}
    58  		return micheline.NewCode(micheline.D_LEFT, inner), nil
    59  	}
    60  }
    61  
    62  func (o *Or[L, R]) UnmarshalPrim(prim micheline.Prim) error {
    63  	switch prim.OpCode {
    64  	case micheline.D_LEFT:
    65  		if len(prim.Args) != 1 {
    66  			return errors.New("prim Left should have 1 arg")
    67  		}
    68  		o.isRight = false
    69  		return UnmarshalPrim(prim.Args[0], &o.l)
    70  	case micheline.D_RIGHT:
    71  		if len(prim.Args) != 1 {
    72  			return errors.New("prim Right should have 1 arg")
    73  		}
    74  		o.isRight = true
    75  		return UnmarshalPrim(prim.Args[0], &o.r)
    76  	default:
    77  		return errors.Errorf("unexpected opCode when unmarshalling Or: %s", prim.OpCode)
    78  	}
    79  }
    80  
    81  func (o Or[L, R]) keyHash() hashType {
    82  	if l, ok := o.Left(); ok {
    83  		valHash := hashFunc(zero[L]())(l)
    84  		return hashBytes(append([]byte{0}, valHash[:]...))
    85  	} else {
    86  		r, _ := o.Right()
    87  		valHash := hashFunc(zero[R]())(r)
    88  		return hashBytes(append([]byte{1}, valHash[:]...))
    89  	}
    90  }