github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/binary/word256.go (about)

     1  // Copyright Monax Industries Limited
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package binary
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/binary"
     9  	"fmt"
    10  	"math/big"
    11  	"sort"
    12  
    13  	"github.com/tmthrgd/go-hex"
    14  )
    15  
    16  var (
    17  	Zero256 = Word256{}
    18  	One256  = LeftPadWord256([]byte{1})
    19  )
    20  
    21  const Word256Bytes = 32
    22  const Word256Bits = Word256Bytes * 8
    23  
    24  var BigWord256Bytes = big.NewInt(Word256Bytes)
    25  
    26  var trimCutSet = string([]byte{0})
    27  
    28  type Word256 [Word256Bytes]byte
    29  
    30  func (w *Word256) UnmarshalText(hexBytes []byte) error {
    31  	bs, err := hex.DecodeString(string(hexBytes))
    32  	if err != nil {
    33  		return err
    34  	}
    35  	copy(w[:], bs)
    36  	return nil
    37  }
    38  
    39  func (w Word256) MarshalText() ([]byte, error) {
    40  	return []byte(w.String()), nil
    41  }
    42  
    43  func (w Word256) String() string {
    44  	return hex.EncodeUpperToString(w[:])
    45  }
    46  
    47  func (w Word256) Copy() Word256 {
    48  	return w
    49  }
    50  
    51  func (w Word256) Bytes() []byte {
    52  	return w[:]
    53  }
    54  
    55  // copied.
    56  func (w Word256) Prefix(n int) []byte {
    57  	return w[:n]
    58  }
    59  
    60  func (w Word256) Postfix(n int) []byte {
    61  	return w[32-n:]
    62  }
    63  
    64  // Get a Word160 embedded a Word256 and padded on the left (as it is for account addresses in EVM)
    65  func (w Word256) Word160() (w160 Word160) {
    66  	copy(w160[:], w[Word256Word160Delta:])
    67  	return
    68  }
    69  
    70  func (w Word256) IsZero() bool {
    71  	accum := byte(0)
    72  	for _, byt := range w {
    73  		accum |= byt
    74  	}
    75  	return accum == 0
    76  }
    77  
    78  func (w Word256) Compare(other Word256) int {
    79  	return bytes.Compare(w[:], other[:])
    80  }
    81  
    82  func (w Word256) UnpadLeft() []byte {
    83  	return bytes.TrimLeft(w[:], trimCutSet)
    84  }
    85  
    86  func (w Word256) UnpadRight() []byte {
    87  	return bytes.TrimRight(w[:], trimCutSet)
    88  }
    89  
    90  // Gogo proto support
    91  func (w *Word256) Marshal() ([]byte, error) {
    92  	if w == nil {
    93  		return nil, nil
    94  	}
    95  	return w.Bytes(), nil
    96  }
    97  
    98  func (w *Word256) Unmarshal(data []byte) error {
    99  	if len(data) == 0 {
   100  		return nil
   101  	}
   102  	if len(data) != Word256Bytes {
   103  		return fmt.Errorf("error unmarshallling Word256 '%X' from bytes: %d bytes but should have %d bytes",
   104  			data, len(data), Word256Bytes)
   105  	}
   106  	copy(w[:], data)
   107  	return nil
   108  }
   109  
   110  func (w *Word256) MarshalTo(data []byte) (int, error) {
   111  	if w == nil {
   112  		return 0, nil
   113  	}
   114  	return copy(data, w[:]), nil
   115  }
   116  
   117  func (w Word256) Size() int {
   118  	return Word256Bytes
   119  }
   120  
   121  func Uint64ToWord256(i uint64) (word Word256) {
   122  	binary.BigEndian.PutUint64(word[24:], i)
   123  	return
   124  }
   125  
   126  func Uint64FromWord256(word Word256) uint64 {
   127  	return binary.BigEndian.Uint64(word.Postfix(8))
   128  }
   129  
   130  func Int64ToWord256(i int64) Word256 {
   131  	return BigIntToWord256(SignExtend(big.NewInt(i), Word256Bits))
   132  }
   133  
   134  func Int64FromWord256(word Word256) int64 {
   135  	return BigIntFromWord256(word).Int64()
   136  }
   137  
   138  func BigIntToWord256(x *big.Int) Word256 {
   139  	return LeftPadWord256(U256(x).Bytes())
   140  }
   141  
   142  func BigIntFromWord256(word Word256) *big.Int {
   143  	return S256(new(big.Int).SetBytes(word[:]))
   144  }
   145  
   146  func RightPadWord256(bz []byte) (word Word256) {
   147  	copy(word[:], bz)
   148  	return
   149  }
   150  
   151  func LeftPadWord256(bz []byte) (word Word256) {
   152  	copy(word[32-len(bz):], bz)
   153  	return
   154  }
   155  
   156  //-------------------------------------
   157  
   158  type Words256 []Word256
   159  
   160  func (ws Words256) Len() int {
   161  	return len(ws)
   162  }
   163  
   164  func (ws Words256) Less(i, j int) bool {
   165  	return ws[i].Compare(ws[j]) < 0
   166  }
   167  
   168  func (ws Words256) Swap(i, j int) {
   169  	ws[i], ws[j] = ws[j], ws[i]
   170  }
   171  
   172  type Tuple256 struct {
   173  	First  Word256
   174  	Second Word256
   175  }
   176  
   177  func (tuple Tuple256) Compare(other Tuple256) int {
   178  	firstCompare := tuple.First.Compare(other.First)
   179  	if firstCompare == 0 {
   180  		return tuple.Second.Compare(other.Second)
   181  	} else {
   182  		return firstCompare
   183  	}
   184  }
   185  
   186  func Tuple256Split(t Tuple256) (Word256, Word256) {
   187  	return t.First, t.Second
   188  }
   189  
   190  type Tuple256Slice []Tuple256
   191  
   192  func (p Tuple256Slice) Len() int { return len(p) }
   193  func (p Tuple256Slice) Less(i, j int) bool {
   194  	return p[i].Compare(p[j]) < 0
   195  }
   196  func (p Tuple256Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
   197  func (p Tuple256Slice) Sort()         { sort.Sort(p) }