github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/util/uint160.go (about) 1 package util 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "strings" 8 9 "github.com/nspcc-dev/neo-go/pkg/io" 10 "github.com/nspcc-dev/neo-go/pkg/util/slice" 11 ) 12 13 // Uint160Size is the size of Uint160 in bytes. 14 const Uint160Size = 20 15 16 // Uint160 is a 20 byte long unsigned integer. 17 type Uint160 [Uint160Size]uint8 18 19 // Uint160DecodeStringBE attempts to decode the given string into a Uint160. 20 func Uint160DecodeStringBE(s string) (Uint160, error) { 21 var u Uint160 22 if len(s) != Uint160Size*2 { 23 return u, fmt.Errorf("expected string size of %d got %d", Uint160Size*2, len(s)) 24 } 25 b, err := hex.DecodeString(s) 26 if err != nil { 27 return u, err 28 } 29 return Uint160DecodeBytesBE(b) 30 } 31 32 // Uint160DecodeStringLE attempts to decode the given string 33 // in little-endian hex encoding into a Uint160. 34 func Uint160DecodeStringLE(s string) (Uint160, error) { 35 var u Uint160 36 if len(s) != Uint160Size*2 { 37 return u, fmt.Errorf("expected string size of %d got %d", Uint160Size*2, len(s)) 38 } 39 40 b, err := hex.DecodeString(s) 41 if err != nil { 42 return u, err 43 } 44 45 return Uint160DecodeBytesLE(b) 46 } 47 48 // Uint160DecodeBytesBE attempts to decode the given bytes into a Uint160. 49 func Uint160DecodeBytesBE(b []byte) (u Uint160, err error) { 50 if len(b) != Uint160Size { 51 return u, fmt.Errorf("expected byte size of %d got %d", Uint160Size, len(b)) 52 } 53 copy(u[:], b) 54 return 55 } 56 57 // Uint160DecodeBytesLE attempts to decode the given bytes in little-endian 58 // into a Uint160. 59 func Uint160DecodeBytesLE(b []byte) (u Uint160, err error) { 60 if len(b) != Uint160Size { 61 return u, fmt.Errorf("expected byte size of %d got %d", Uint160Size, len(b)) 62 } 63 64 for i := range b { 65 u[Uint160Size-i-1] = b[i] 66 } 67 68 return 69 } 70 71 // BytesBE returns a big-endian byte representation of u. 72 func (u Uint160) BytesBE() []byte { 73 return u[:] 74 } 75 76 // BytesLE returns a little-endian byte representation of u. 77 func (u Uint160) BytesLE() []byte { 78 return slice.CopyReverse(u.BytesBE()) 79 } 80 81 // String implements the stringer interface. 82 func (u Uint160) String() string { 83 return u.StringBE() 84 } 85 86 // StringBE returns string representations of u with big-endian byte order. 87 func (u Uint160) StringBE() string { 88 return hex.EncodeToString(u.BytesBE()) 89 } 90 91 // StringLE returns string representations of u with little-endian byte order. 92 func (u Uint160) StringLE() string { 93 return hex.EncodeToString(u.BytesLE()) 94 } 95 96 // Reverse returns a reversed representation of u. 97 func (u Uint160) Reverse() (r Uint160) { 98 for i := 0; i < Uint160Size; i++ { 99 r[i] = u[Uint160Size-i-1] 100 } 101 102 return 103 } 104 105 // Equals returns true if both Uint160 values are the same. 106 func (u Uint160) Equals(other Uint160) bool { 107 return u == other 108 } 109 110 // Less returns true if this value is less than the given Uint160 value. It's 111 // primarily intended to be used for sorting purposes. 112 func (u Uint160) Less(other Uint160) bool { 113 for k := range u { 114 if u[k] == other[k] { 115 continue 116 } 117 return u[k] < other[k] 118 } 119 return false 120 } 121 122 // UnmarshalJSON implements the json unmarshaller interface. 123 func (u *Uint160) UnmarshalJSON(data []byte) (err error) { 124 var js string 125 if err = json.Unmarshal(data, &js); err != nil { 126 return err 127 } 128 js = strings.TrimPrefix(js, "0x") 129 *u, err = Uint160DecodeStringLE(js) 130 return err 131 } 132 133 // MarshalJSON implements the json marshaller interface. 134 func (u Uint160) MarshalJSON() ([]byte, error) { 135 r := make([]byte, 3+Uint160Size*2+1) 136 copy(r, `"0x`) 137 r[len(r)-1] = '"' 138 slice.Reverse(u[:]) // u is a copy, so we can mangle it in any way. 139 hex.Encode(r[3:], u[:]) 140 return r, nil 141 } 142 143 // UnmarshalYAML implements the YAML Unmarshaler interface. 144 func (u *Uint160) UnmarshalYAML(unmarshal func(any) error) error { 145 var s string 146 147 err := unmarshal(&s) 148 if err != nil { 149 return err 150 } 151 152 s = strings.TrimPrefix(s, "0x") 153 *u, err = Uint160DecodeStringLE(s) 154 return err 155 } 156 157 // MarshalYAML implements the YAML marshaller interface. 158 func (u Uint160) MarshalYAML() (any, error) { 159 return "0x" + u.StringLE(), nil 160 } 161 162 // EncodeBinary implements the Serializable interface. 163 func (u *Uint160) EncodeBinary(bw *io.BinWriter) { 164 bw.WriteBytes(u[:]) 165 } 166 167 // DecodeBinary implements the Serializable interface. 168 func (u *Uint160) DecodeBinary(br *io.BinReader) { 169 br.ReadBytes(u[:]) 170 }