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