forked from linhbkhn95/int256
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconversion.go
201 lines (180 loc) · 6.2 KB
/
conversion.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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
package int256
import (
"database/sql/driver"
"errors"
"strings"
"github.com/holiman/uint256"
)
// SetFromDecimal sets z from the given string, interpreted as a decimal number.
// OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 10) method.
// Notable differences:
// - This method does not accept underscore input, e.g. "100_000"
func (z *Int) SetFromDecimal(decimal string) (err error) {
z.initiateAbs()
if strings.HasPrefix(decimal, "-") {
z.neg = true
decimal = decimal[1:]
// take into account the double sign at the beginning which create an error in big.Int
if strings.HasPrefix(decimal, "+") || strings.HasPrefix(decimal, "-") {
return ErrMultipleSignAtStart
}
}
return z.abs.SetFromDecimal(decimal)
}
// FromDecimal is a convenience-constructor to create an Int from a
// decimal (base 10) string. Numbers larger than 256 bits are not accepted.
func FromDecimal(decimal string) (*Int, error) {
var z Int
if err := z.SetFromDecimal(decimal); err != nil {
return nil, err
}
return &z, nil
}
// MustFromDecimal is a convenience-constructor to create an Int from a
// decimal (base 10) string.
// Returns a new Int and panics if any error occurred.
func MustFromDecimal(decimal string) *Int {
var z Int
if err := z.SetFromDecimal(decimal); err != nil {
panic(err)
}
return &z
}
// SetFromHex sets z from the given string, interpreted as a hexadecimal number.
// OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 16) method.
// Notable differences:
// - This method _require_ "0x", "0X", "-0x" or "-0X" prefix.
// - This method does not accept zero-prefixed hex, e.g. "0x0001"
// - This method does not accept underscore input, e.g. "100_000",
// - negative value should be prefixed with "-" like "-0x0"
func (z *Int) SetFromHex(hex string) error {
z.initiateAbs()
if strings.HasPrefix(hex, "-") {
z.neg = true
hex = hex[1:]
// take into account the double sign at the beginning which create an error in big.Int
if strings.HasPrefix(hex, "+") || strings.HasPrefix(hex, "-") {
return ErrMultipleSignAtStart
}
}
return z.abs.SetFromHex(hex)
}
// FromHex is a convenience-constructor to create an Int from
// a hexadecimal string. The string is required to be '0x' or "-0x"-prefixed
// Numbers larger than 256 bits are not accepted.
func FromHex(hex string) (*Int, error) {
var z Int
if err := z.SetFromHex(hex); err != nil {
return nil, err
}
return &z, nil
}
// MustFromHex is a convenience-constructor to create an Int from
// a hexadecimal string.
// Returns a new Int and panics if any error occurred.
func MustFromHex(hex string) *Int {
var z Int
if err := z.SetFromHex(hex); err != nil {
panic(err)
}
return &z
}
// Hex encodes z in 0x-prefixed or -0x-prefixed hexadecimal form.
func (z *Int) Hex() string {
z.initiateAbs()
if z.abs.IsZero() {
return "0x0"
}
if z.neg {
return "-" + z.abs.Hex()
}
return z.abs.Hex()
}
// Dec returns the decimal representation of z.
func (z *Int) Dec() string {
z.initiateAbs()
if z.abs.IsZero() {
return "0"
}
if z.neg {
return "-" + z.abs.Dec()
}
return z.abs.Dec()
}
// MarshalText implements encoding.TextMarshaler
// MarshalText marshals using the decimal representation
func (z *Int) MarshalText() ([]byte, error) {
return []byte(z.Dec()), nil
}
// UnmarshalText implements encoding.TextUnmarshaler. This method
// can unmarshal either hexadecimal or decimal.
// - For hexadecimal, the input _must_ be prefixed with -0x, -0X, 0x or 0X
func (z *Int) UnmarshalText(input []byte) error {
if len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') {
return z.SetFromHex(string(input))
}
if len(input) >= 3 && input[0] == '-' && input[1] == '0' && (input[2] == 'x' || input[2] == 'X') {
return z.SetFromHex(string(input))
}
return z.SetFromDecimal(string(input))
}
// MarshalJSON implements json.Marshaler.
// MarshalJSON marshals using the 'decimal string' representation. This is _not_ compatible
// with big.Int: big.Int marshals into JSON 'native' numeric format.
//
// The JSON native format is, on some platforms, (e.g. javascript), limited to 53-bit large
// integer space. Thus, U256 uses string-format, which is not compatible with
// big.int (big.Int refuses to unmarshal a string representation).
func (z *Int) MarshalJSON() ([]byte, error) {
return []byte(`"` + z.Dec() + `"`), nil
}
// UnmarshalJSON implements json.Unmarshaler. UnmarshalJSON accepts either
// - Quoted string: either hexadecimal OR decimal
// - For hexadecimal, the input _must_ be prefixed with -0x, -0X, 0x or 0X
// - Not quoted string: only decimal
func (z *Int) UnmarshalJSON(input []byte) error {
if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' {
// if not quoted, it must be decimal
return z.SetFromDecimal(string(input))
}
return z.UnmarshalText(input[1 : len(input)-1])
}
// String returns the decimal encoding of z
func (z *Int) String() string {
return z.Dec()
}
// Value implements the database/sql/driver Valuer interface.
// It encodes a base 10 string.
// In Postgres, this will work with both integer and the Numeric/Decimal types
// In MariaDB/MySQL, this will work with the Numeric/Decimal types up to 65 digits, however any more and you should use either VarChar or Char(79)
// In SqLite, use TEXT
func (z *Int) Value() (driver.Value, error) {
return z.Dec(), nil
}
var (
ErrMultipleSignAtStart = errors.New("multiple sign at the beginning")
)
// CmpU compares z (Int) and x(Uint) and returns:
//
// -1 if z < x
// 0 if z == x
// +1 if z > x
func (z *Int) CmpU(x *uint256.Int) int {
if z.abs.IsZero() && x.IsZero() {
return 0
}
if z.neg {
return -1
}
return z.abs.Cmp(x)
}
// Abs Absolute value of z having the type uint256.Int
func (z *Int) Abs() *uint256.Int {
return z.abs.Clone()
}
// FromUInt256 create a int256.Int from a uint256.Int
func FromUInt256(x *uint256.Int) *Int {
z := new(Int)
z.abs = x.Clone()
return z
}