github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/util/uint256.go (about)

     1  package util
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/nspcc-dev/neo-go/pkg/io"
    11  	"github.com/nspcc-dev/neo-go/pkg/util/slice"
    12  )
    13  
    14  // Uint256Size is the size of Uint256 in bytes.
    15  const Uint256Size = 32
    16  
    17  // Uint256 is a 32 byte long unsigned integer.
    18  type Uint256 [Uint256Size]uint8
    19  
    20  // Uint256DecodeStringLE attempts to decode the given string (in LE representation) into a Uint256.
    21  func Uint256DecodeStringLE(s string) (u Uint256, err error) {
    22  	if len(s) != Uint256Size*2 {
    23  		return u, fmt.Errorf("expected string size of %d got %d", Uint256Size*2, len(s))
    24  	}
    25  	b, err := hex.DecodeString(s)
    26  	if err != nil {
    27  		return u, err
    28  	}
    29  	slice.Reverse(b)
    30  	return Uint256DecodeBytesBE(b)
    31  }
    32  
    33  // Uint256DecodeStringBE attempts to decode the given string (in BE representation)
    34  // into a Uint256.
    35  func Uint256DecodeStringBE(s string) (u Uint256, err error) {
    36  	if len(s) != Uint256Size*2 {
    37  		return u, fmt.Errorf("expected string size of %d got %d", Uint256Size*2, len(s))
    38  	}
    39  
    40  	b, err := hex.DecodeString(s)
    41  	if err != nil {
    42  		return u, err
    43  	}
    44  
    45  	return Uint256DecodeBytesBE(b)
    46  }
    47  
    48  // Uint256DecodeBytesBE attempts to decode the given string (in BE representation) into a Uint256.
    49  func Uint256DecodeBytesBE(b []byte) (u Uint256, err error) {
    50  	if len(b) != Uint256Size {
    51  		return u, fmt.Errorf("expected []byte of size %d got %d", Uint256Size, len(b))
    52  	}
    53  	copy(u[:], b)
    54  	return u, nil
    55  }
    56  
    57  // Uint256DecodeBytesLE attempts to decode the given string (in LE representation) into a Uint256.
    58  func Uint256DecodeBytesLE(b []byte) (u Uint256, err error) {
    59  	b = slice.CopyReverse(b)
    60  	return Uint256DecodeBytesBE(b)
    61  }
    62  
    63  // BytesBE returns a byte slice representation of u.
    64  func (u Uint256) BytesBE() []byte {
    65  	return u[:]
    66  }
    67  
    68  // Reverse reverses the Uint256 object.
    69  func (u Uint256) Reverse() Uint256 {
    70  	res, _ := Uint256DecodeBytesLE(u.BytesBE())
    71  	return res
    72  }
    73  
    74  // BytesLE return a little-endian byte representation of u.
    75  func (u Uint256) BytesLE() []byte {
    76  	return slice.CopyReverse(u.BytesBE())
    77  }
    78  
    79  // Equals returns true if both Uint256 values are the same.
    80  func (u Uint256) Equals(other Uint256) bool {
    81  	return u == other
    82  }
    83  
    84  // String implements the stringer interface.
    85  func (u Uint256) String() string {
    86  	return u.StringBE()
    87  }
    88  
    89  // StringBE produces string representation of Uint256 with BE byte order.
    90  func (u Uint256) StringBE() string {
    91  	return hex.EncodeToString(u.BytesBE())
    92  }
    93  
    94  // StringLE produces string representation of Uint256 with LE byte order.
    95  func (u Uint256) StringLE() string {
    96  	return hex.EncodeToString(u.BytesLE())
    97  }
    98  
    99  // UnmarshalJSON implements the json unmarshaller interface.
   100  func (u *Uint256) UnmarshalJSON(data []byte) (err error) {
   101  	var js string
   102  	if err = json.Unmarshal(data, &js); err != nil {
   103  		return err
   104  	}
   105  	js = strings.TrimPrefix(js, "0x")
   106  	*u, err = Uint256DecodeStringLE(js)
   107  	return err
   108  }
   109  
   110  // MarshalJSON implements the json marshaller interface.
   111  func (u Uint256) MarshalJSON() ([]byte, error) {
   112  	r := make([]byte, 3+Uint256Size*2+1)
   113  	copy(r, `"0x`)
   114  	r[len(r)-1] = '"'
   115  	slice.Reverse(u[:]) // u is a copy, so we can mangle it in any way.
   116  	hex.Encode(r[3:], u[:])
   117  	return r, nil
   118  }
   119  
   120  // CompareTo compares two Uint256 with each other. Possible output: 1, -1, 0
   121  //
   122  // 1 implies u > other.
   123  // -1 implies u < other.
   124  // 0 implies  u = other.
   125  func (u Uint256) CompareTo(other Uint256) int { return bytes.Compare(u[:], other[:]) }
   126  
   127  // EncodeBinary implements the io.Serializable interface.
   128  func (u *Uint256) EncodeBinary(w *io.BinWriter) {
   129  	w.WriteBytes(u[:])
   130  }
   131  
   132  // DecodeBinary implements the io.Serializable interface.
   133  func (u *Uint256) DecodeBinary(r *io.BinReader) {
   134  	r.ReadBytes(u[:])
   135  }