util.gno
3.94 Kb ยท 169 lines
1package v1
2
3import (
4 b64 "encoding/base64"
5 "math"
6 "strconv"
7
8 u256 "gno.land/p/gnoswap/uint256"
9 "gno.land/p/nt/avl"
10 "gno.land/p/nt/ufmt"
11 "gno.land/p/onbloc/json"
12)
13
14// marshal data to json string
15func marshal(data *json.Node) string {
16 b, err := json.Marshal(data)
17 if err != nil {
18 panic(err.Error())
19 }
20
21 return string(b)
22}
23
24// b64Encode encodes data to base64 string
25func b64Encode(data string) string {
26 return string(b64.StdEncoding.EncodeToString([]byte(data)))
27}
28
29// formatUint formats a uint64 to a string
30func formatUint(v uint64) string {
31 return strconv.FormatUint(v, 10)
32}
33
34// formatInt formats an int64 to a string
35func formatInt(v int64) string {
36 return strconv.FormatInt(v, 10)
37}
38
39// getUint64FromTree returns the uint64 value from the tree
40func getUint64FromTree(tree *avl.Tree, key string) uint64 {
41 value, exists := tree.Get(key)
42 if !exists {
43 return 0
44 }
45
46 v, ok := value.(uint64)
47 if !ok {
48 panic(ufmt.Sprintf("failed to cast value to uint64: %T", value))
49 }
50
51 return v
52}
53
54// updateUint64InTree updates the uint64 value in the tree
55func updateUint64InTree(tree *avl.Tree, key string, delta uint64, add bool) uint64 {
56 current := getUint64FromTree(tree, key)
57 var newValue uint64
58 if add {
59 newValue = safeAddUint64(current, delta)
60 } else {
61 if current < delta {
62 panic(makeErrorWithDetails(
63 errNotEnoughBalance,
64 ufmt.Sprintf("not enough balance: current(%d) < requested(%d)", current, delta),
65 ))
66 }
67 newValue = safeSubUint64(current, delta)
68 }
69
70 tree.Set(key, newValue)
71
72 return newValue
73}
74
75// getOrCreateInnerTree returns the inner tree for the given key
76func getOrCreateInnerTree(tree *avl.Tree, key string) *avl.Tree {
77 value, exists := tree.Get(key)
78 if !exists {
79 innerTree := avl.NewTree()
80 tree.Set(key, innerTree)
81 return innerTree
82 }
83
84 v, ok := value.(*avl.Tree)
85 if !ok {
86 panic(ufmt.Sprintf("failed to cast value to *avl.Tree: %T", value))
87 }
88
89 return v
90}
91
92// milliToSec converts milliseconds to seconds
93func milliToSec(ms int64) int64 {
94 var msPerSec int64 = 1000
95 return ms / msPerSec
96}
97
98// safeConvertToInt64 safely converts a *u256.Uint value to an int64, ensuring no overflow.
99//
100// This function attempts to convert the given *u256.Uint value to an int64. If the value exceeds
101// the maximum allowable range for int64 (`2^63 - 1`), it triggers a panic with a descriptive error message.
102//
103// Parameters:
104// - value (*u256.Uint): The unsigned 256-bit integer to be converted.
105//
106// Returns:
107// - int64: The converted value if it falls within the int64 range.
108//
109// Panics:
110// - If the `value` exceeds the range of int64, the function will panic with an error indicating
111// the overflow and the original value.
112func safeConvertToInt64(value *u256.Uint) int64 {
113 const INT64_MAX = 9223372036854775807
114 const MAX_INT64 = "9223372036854775807"
115
116 res, overflow := value.Uint64WithOverflow()
117 if overflow || res > uint64(INT64_MAX) {
118 panic(ufmt.Sprintf(
119 "amount(%s) overflows int64 range (max %s)",
120 value.ToString(),
121 MAX_INT64,
122 ))
123 }
124 return int64(res)
125}
126
127// safeAddInt64 performs safe addition of int64 values, panicking on overflow or underflow
128func safeAddInt64(a, b int64) int64 {
129 if a > 0 && b > math.MaxInt64-a {
130 panic("int64 addition overflow")
131 }
132
133 if a < 0 && b < math.MinInt64-a {
134 panic("int64 addition underflow")
135 }
136
137 return a + b
138}
139
140// safeSubInt64 performs safe subtraction of int64 values, panicking on overflow or underflow
141func safeSubInt64(a, b int64) int64 {
142 if b > 0 && a < math.MinInt64+b {
143 panic("int64 subtraction underflow")
144 }
145
146 if b < 0 && a > math.MaxInt64+b {
147 panic("int64 subtraction overflow")
148 }
149
150 return a - b
151}
152
153// safeAddUint64 performs safe addition of uint64 values, panicking on overflow
154func safeAddUint64(a, b uint64) uint64 {
155 if a > math.MaxUint64-b {
156 panic("uint64 addition overflow")
157 }
158
159 return a + b
160}
161
162// safeSubUint64 performs safe subtraction of uint64 values, panicking on underflow
163func safeSubUint64(a, b uint64) uint64 {
164 if a < b {
165 panic("uint64 subtraction underflow")
166 }
167
168 return a - b
169}