conversion.gno
16.50 Kb · 531 lines
1// conversions contains methods for converting Uint instances to other types and vice versa.
2// This includes conversions to and from basic types such as uint64 and int32, as well as string representations
3// and byte slices. Additionally, it covers marshaling and unmarshaling for JSON and other text formats.
4package uint256
5
6import (
7 "encoding/binary"
8 "strconv"
9)
10
11// Uint64 returns the lower 64 bits of z as a uint64.
12func (z *Uint) Uint64() uint64 {
13 return z[0]
14}
15
16// Int64 returns the lower 64 bits of z as an int64.
17func (z *Uint) Int64() int64 {
18 return int64(z.Uint64())
19}
20
21// Uint64WithOverflow returns the lower 64 bits of z and true if overflow occurred.
22func (z *Uint) Uint64WithOverflow() (uint64, bool) {
23 return z[0], (z[1] | z[2] | z[3]) != 0
24}
25
26// SetUint64 sets z to the value of x and returns z.
27func (z *Uint) SetUint64(x uint64) *Uint {
28 z[3], z[2], z[1], z[0] = 0, 0, 0, x
29 return z
30}
31
32// IsUint64 reports whether z can be represented as a uint64.
33func (z *Uint) IsUint64() bool {
34 return (z[1] | z[2] | z[3]) == 0
35}
36
37// Dec returns the decimal representation of z.
38func (z *Uint) Dec() string {
39 if z.IsZero() {
40 return "0"
41 }
42 if z.IsUint64() {
43 return strconv.FormatUint(z.Uint64(), 10)
44 }
45
46 // The max uint64 value being 18446744073709551615, the largest
47 // power-of-ten below that is 10000000000000000000.
48 // When we do a DivMod using that number, the remainder that we
49 // get back is the lower part of the output.
50 //
51 // The ascii-output of remainder will never exceed 19 bytes (since it will be
52 // below 10000000000000000000).
53 //
54 // Algorithm example using 100 as divisor
55 //
56 // 12345 % 100 = 45 (rem)
57 // 12345 / 100 = 123 (quo)
58 // -> output '45', continue iterate on 123
59 var (
60 // out is 98 bytes long: 78 (max size of a string without leading zeroes,
61 // plus slack so we can copy 19 bytes every iteration).
62 // We init it with zeroes, because when strconv appends the ascii representations,
63 // it will omit leading zeroes.
64 out [98]byte
65 divisor Uint
66 y = *z // copy z to avoid modifying it
67 pos = len(out) // position to write to
68 buf [19]byte // buffer to write uint64:s to
69 bufSlice []byte = buf[:0] // slice for strconv.AppendUint
70 )
71
72 // Initialize out array with '0's
73 for i := range out {
74 out[i] = '0'
75 }
76
77 // Set divisor to 10^19
78 divisor.SetUint64(10000000000000000000)
79
80 for {
81 // Obtain Q and R for divisor
82 var quot Uint
83 rem := udivrem(quot[:], y[:], &divisor)
84 y = quot // Set Q for next loop
85 // Convert the R to ascii representation
86 bufSlice = strconv.AppendUint(bufSlice[:0], rem.Uint64(), 10)
87 // Copy in the ascii digits
88 copy(out[pos-len(bufSlice):], bufSlice)
89 if y.IsZero() {
90 break
91 }
92 // Move 19 digits left
93 pos -= 19
94 }
95 // skip leading zeroes by only using the 'used size' of bufSlice
96 return string(out[pos-len(bufSlice):])
97}
98
99// ToString returns the decimal string representation of z.
100// Returns an empty string if z is nil. This method doesn't exist in holiman's uint256.
101func (z *Uint) ToString() string {
102 if z == nil {
103 return ""
104 }
105
106 return z.Dec()
107}
108
109// SetBytes interprets buf as a big-endian unsigned integer and sets z to that value.
110// If buf is larger than 32 bytes, uses only the last 32 bytes. Returns z.
111func (z *Uint) SetBytes(buf []byte) *Uint {
112 switch l := len(buf); l {
113 case 0:
114 z.Clear()
115 case 1:
116 z.SetBytes1(buf)
117 case 2:
118 z.SetBytes2(buf)
119 case 3:
120 z.SetBytes3(buf)
121 case 4:
122 z.SetBytes4(buf)
123 case 5:
124 z.SetBytes5(buf)
125 case 6:
126 z.SetBytes6(buf)
127 case 7:
128 z.SetBytes7(buf)
129 case 8:
130 z.SetBytes8(buf)
131 case 9:
132 z.SetBytes9(buf)
133 case 10:
134 z.SetBytes10(buf)
135 case 11:
136 z.SetBytes11(buf)
137 case 12:
138 z.SetBytes12(buf)
139 case 13:
140 z.SetBytes13(buf)
141 case 14:
142 z.SetBytes14(buf)
143 case 15:
144 z.SetBytes15(buf)
145 case 16:
146 z.SetBytes16(buf)
147 case 17:
148 z.SetBytes17(buf)
149 case 18:
150 z.SetBytes18(buf)
151 case 19:
152 z.SetBytes19(buf)
153 case 20:
154 z.SetBytes20(buf)
155 case 21:
156 z.SetBytes21(buf)
157 case 22:
158 z.SetBytes22(buf)
159 case 23:
160 z.SetBytes23(buf)
161 case 24:
162 z.SetBytes24(buf)
163 case 25:
164 z.SetBytes25(buf)
165 case 26:
166 z.SetBytes26(buf)
167 case 27:
168 z.SetBytes27(buf)
169 case 28:
170 z.SetBytes28(buf)
171 case 29:
172 z.SetBytes29(buf)
173 case 30:
174 z.SetBytes30(buf)
175 case 31:
176 z.SetBytes31(buf)
177 default:
178 z.SetBytes32(buf[l-32:])
179 }
180 return z
181}
182
183// SetBytes1 sets z from a 1-byte big-endian slice and returns z.
184// Panics if input is shorter than 1 byte.
185func (z *Uint) SetBytes1(in []byte) *Uint {
186 z[3], z[2], z[1] = 0, 0, 0
187 z[0] = uint64(in[0])
188 return z
189}
190
191// SetBytes2 sets z from a 2-byte big-endian slice and returns z.
192// Panics if input is shorter than 2 bytes.
193func (z *Uint) SetBytes2(in []byte) *Uint {
194 _ = in[1] // bounds check hint to compiler; see golang.org/issue/14808
195 z[3], z[2], z[1] = 0, 0, 0
196 z[0] = uint64(binary.BigEndian.Uint16(in[0:2]))
197 return z
198}
199
200// SetBytes3 sets z from a 3-byte big-endian slice and returns z.
201// Panics if input is shorter than 3 bytes.
202func (z *Uint) SetBytes3(in []byte) *Uint {
203 _ = in[2] // bounds check hint to compiler; see golang.org/issue/14808
204 z[3], z[2], z[1] = 0, 0, 0
205 z[0] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
206 return z
207}
208
209// SetBytes4 sets z from a 4-byte big-endian slice and returns z.
210// Panics if input is shorter than 4 bytes.
211func (z *Uint) SetBytes4(in []byte) *Uint {
212 _ = in[3] // bounds check hint to compiler; see golang.org/issue/14808
213 z[3], z[2], z[1] = 0, 0, 0
214 z[0] = uint64(binary.BigEndian.Uint32(in[0:4]))
215 return z
216}
217
218// SetBytes5 sets z from a 5-byte big-endian slice and returns z.
219// Panics if input is shorter than 5 bytes.
220func (z *Uint) SetBytes5(in []byte) *Uint {
221 _ = in[4] // bounds check hint to compiler; see golang.org/issue/14808
222 z[3], z[2], z[1] = 0, 0, 0
223 z[0] = bigEndianUint40(in[0:5])
224 return z
225}
226
227// SetBytes6 sets z from a 6-byte big-endian slice and returns z.
228// Panics if input is shorter than 6 bytes.
229func (z *Uint) SetBytes6(in []byte) *Uint {
230 _ = in[5] // bounds check hint to compiler; see golang.org/issue/14808
231 z[3], z[2], z[1] = 0, 0, 0
232 z[0] = bigEndianUint48(in[0:6])
233 return z
234}
235
236// SetBytes7 sets z from a 7-byte big-endian slice and returns z.
237// Panics if input is shorter than 7 bytes.
238func (z *Uint) SetBytes7(in []byte) *Uint {
239 _ = in[6] // bounds check hint to compiler; see golang.org/issue/14808
240 z[3], z[2], z[1] = 0, 0, 0
241 z[0] = bigEndianUint56(in[0:7])
242 return z
243}
244
245// SetBytes8 sets z from an 8-byte big-endian slice and returns z.
246// Panics if input is shorter than 8 bytes.
247func (z *Uint) SetBytes8(in []byte) *Uint {
248 _ = in[7] // bounds check hint to compiler; see golang.org/issue/14808
249 z[3], z[2], z[1] = 0, 0, 0
250 z[0] = binary.BigEndian.Uint64(in[0:8])
251 return z
252}
253
254// SetBytes9 sets z from a 9-byte big-endian slice and returns z.
255// Panics if input is shorter than 9 bytes.
256func (z *Uint) SetBytes9(in []byte) *Uint {
257 _ = in[8] // bounds check hint to compiler; see golang.org/issue/14808
258 z[3], z[2] = 0, 0
259 z[1] = uint64(in[0])
260 z[0] = binary.BigEndian.Uint64(in[1:9])
261 return z
262}
263
264// SetBytes10 sets z from a 10-byte big-endian slice and returns z.
265// Panics if input is shorter than 10 bytes.
266func (z *Uint) SetBytes10(in []byte) *Uint {
267 _ = in[9] // bounds check hint to compiler; see golang.org/issue/14808
268 z[3], z[2] = 0, 0
269 z[1] = uint64(binary.BigEndian.Uint16(in[0:2]))
270 z[0] = binary.BigEndian.Uint64(in[2:10])
271 return z
272}
273
274// SetBytes11 sets z from an 11-byte big-endian slice and returns z.
275// Panics if input is shorter than 11 bytes.
276func (z *Uint) SetBytes11(in []byte) *Uint {
277 _ = in[10] // bounds check hint to compiler; see golang.org/issue/14808
278 z[3], z[2] = 0, 0
279 z[1] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
280 z[0] = binary.BigEndian.Uint64(in[3:11])
281 return z
282}
283
284// SetBytes12 sets z from a 12-byte big-endian slice and returns z.
285// Panics if input is shorter than 12 bytes.
286func (z *Uint) SetBytes12(in []byte) *Uint {
287 _ = in[11] // bounds check hint to compiler; see golang.org/issue/14808
288 z[3], z[2] = 0, 0
289 z[1] = uint64(binary.BigEndian.Uint32(in[0:4]))
290 z[0] = binary.BigEndian.Uint64(in[4:12])
291 return z
292}
293
294// SetBytes13 sets z from a 13-byte big-endian slice and returns z.
295// Panics if input is shorter than 13 bytes.
296func (z *Uint) SetBytes13(in []byte) *Uint {
297 _ = in[12] // bounds check hint to compiler; see golang.org/issue/14808
298 z[3], z[2] = 0, 0
299 z[1] = bigEndianUint40(in[0:5])
300 z[0] = binary.BigEndian.Uint64(in[5:13])
301 return z
302}
303
304// SetBytes14 sets z from a 14-byte big-endian slice and returns z.
305// Panics if input is shorter than 14 bytes.
306func (z *Uint) SetBytes14(in []byte) *Uint {
307 _ = in[13] // bounds check hint to compiler; see golang.org/issue/14808
308 z[3], z[2] = 0, 0
309 z[1] = bigEndianUint48(in[0:6])
310 z[0] = binary.BigEndian.Uint64(in[6:14])
311 return z
312}
313
314// SetBytes15 sets z from a 15-byte big-endian slice and returns z.
315// Panics if input is shorter than 15 bytes.
316func (z *Uint) SetBytes15(in []byte) *Uint {
317 _ = in[14] // bounds check hint to compiler; see golang.org/issue/14808
318 z[3], z[2] = 0, 0
319 z[1] = bigEndianUint56(in[0:7])
320 z[0] = binary.BigEndian.Uint64(in[7:15])
321 return z
322}
323
324// SetBytes16 sets z from a 16-byte big-endian slice and returns z.
325// Panics if input is shorter than 16 bytes.
326func (z *Uint) SetBytes16(in []byte) *Uint {
327 _ = in[15] // bounds check hint to compiler; see golang.org/issue/14808
328 z[3], z[2] = 0, 0
329 z[1] = binary.BigEndian.Uint64(in[0:8])
330 z[0] = binary.BigEndian.Uint64(in[8:16])
331 return z
332}
333
334// SetBytes17 sets z from a 17-byte big-endian slice and returns z.
335// Panics if input is shorter than 17 bytes.
336func (z *Uint) SetBytes17(in []byte) *Uint {
337 _ = in[16] // bounds check hint to compiler; see golang.org/issue/14808
338 z[3] = 0
339 z[2] = uint64(in[0])
340 z[1] = binary.BigEndian.Uint64(in[1:9])
341 z[0] = binary.BigEndian.Uint64(in[9:17])
342 return z
343}
344
345// SetBytes18 sets z from an 18-byte big-endian slice and returns z.
346// Panics if input is shorter than 18 bytes.
347func (z *Uint) SetBytes18(in []byte) *Uint {
348 _ = in[17] // bounds check hint to compiler; see golang.org/issue/14808
349 z[3] = 0
350 z[2] = uint64(binary.BigEndian.Uint16(in[0:2]))
351 z[1] = binary.BigEndian.Uint64(in[2:10])
352 z[0] = binary.BigEndian.Uint64(in[10:18])
353 return z
354}
355
356// SetBytes19 sets z from a 19-byte big-endian slice and returns z.
357// Panics if input is shorter than 19 bytes.
358func (z *Uint) SetBytes19(in []byte) *Uint {
359 _ = in[18] // bounds check hint to compiler; see golang.org/issue/14808
360 z[3] = 0
361 z[2] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
362 z[1] = binary.BigEndian.Uint64(in[3:11])
363 z[0] = binary.BigEndian.Uint64(in[11:19])
364 return z
365}
366
367// SetBytes20 sets z from a 20-byte big-endian slice and returns z.
368// Panics if input is shorter than 20 bytes.
369func (z *Uint) SetBytes20(in []byte) *Uint {
370 _ = in[19] // bounds check hint to compiler; see golang.org/issue/14808
371 z[3] = 0
372 z[2] = uint64(binary.BigEndian.Uint32(in[0:4]))
373 z[1] = binary.BigEndian.Uint64(in[4:12])
374 z[0] = binary.BigEndian.Uint64(in[12:20])
375 return z
376}
377
378// SetBytes21 sets z from a 21-byte big-endian slice and returns z.
379// Panics if input is shorter than 21 bytes.
380func (z *Uint) SetBytes21(in []byte) *Uint {
381 _ = in[20] // bounds check hint to compiler; see golang.org/issue/14808
382 z[3] = 0
383 z[2] = bigEndianUint40(in[0:5])
384 z[1] = binary.BigEndian.Uint64(in[5:13])
385 z[0] = binary.BigEndian.Uint64(in[13:21])
386 return z
387}
388
389// SetBytes22 sets z from a 22-byte big-endian slice and returns z.
390// Panics if input is shorter than 22 bytes.
391func (z *Uint) SetBytes22(in []byte) *Uint {
392 _ = in[21] // bounds check hint to compiler; see golang.org/issue/14808
393 z[3] = 0
394 z[2] = bigEndianUint48(in[0:6])
395 z[1] = binary.BigEndian.Uint64(in[6:14])
396 z[0] = binary.BigEndian.Uint64(in[14:22])
397 return z
398}
399
400// SetBytes23 sets z from a 23-byte big-endian slice and returns z.
401// Panics if input is shorter than 23 bytes.
402func (z *Uint) SetBytes23(in []byte) *Uint {
403 _ = in[22] // bounds check hint to compiler; see golang.org/issue/14808
404 z[3] = 0
405 z[2] = bigEndianUint56(in[0:7])
406 z[1] = binary.BigEndian.Uint64(in[7:15])
407 z[0] = binary.BigEndian.Uint64(in[15:23])
408 return z
409}
410
411// SetBytes24 sets z from a 24-byte big-endian slice and returns z.
412// Panics if input is shorter than 24 bytes.
413func (z *Uint) SetBytes24(in []byte) *Uint {
414 _ = in[23] // bounds check hint to compiler; see golang.org/issue/14808
415 z[3] = 0
416 z[2] = binary.BigEndian.Uint64(in[0:8])
417 z[1] = binary.BigEndian.Uint64(in[8:16])
418 z[0] = binary.BigEndian.Uint64(in[16:24])
419 return z
420}
421
422// SetBytes25 sets z from a 25-byte big-endian slice and returns z.
423// Panics if input is shorter than 25 bytes.
424func (z *Uint) SetBytes25(in []byte) *Uint {
425 _ = in[24] // bounds check hint to compiler; see golang.org/issue/14808
426 z[3] = uint64(in[0])
427 z[2] = binary.BigEndian.Uint64(in[1:9])
428 z[1] = binary.BigEndian.Uint64(in[9:17])
429 z[0] = binary.BigEndian.Uint64(in[17:25])
430 return z
431}
432
433// SetBytes26 sets z from a 26-byte big-endian slice and returns z.
434// Panics if input is shorter than 26 bytes.
435func (z *Uint) SetBytes26(in []byte) *Uint {
436 _ = in[25] // bounds check hint to compiler; see golang.org/issue/14808
437 z[3] = uint64(binary.BigEndian.Uint16(in[0:2]))
438 z[2] = binary.BigEndian.Uint64(in[2:10])
439 z[1] = binary.BigEndian.Uint64(in[10:18])
440 z[0] = binary.BigEndian.Uint64(in[18:26])
441 return z
442}
443
444// SetBytes27 sets z from a 27-byte big-endian slice and returns z.
445// Panics if input is shorter than 27 bytes.
446func (z *Uint) SetBytes27(in []byte) *Uint {
447 _ = in[26] // bounds check hint to compiler; see golang.org/issue/14808
448 z[3] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
449 z[2] = binary.BigEndian.Uint64(in[3:11])
450 z[1] = binary.BigEndian.Uint64(in[11:19])
451 z[0] = binary.BigEndian.Uint64(in[19:27])
452 return z
453}
454
455// SetBytes28 sets z from a 28-byte big-endian slice and returns z.
456// Panics if input is shorter than 28 bytes.
457func (z *Uint) SetBytes28(in []byte) *Uint {
458 _ = in[27] // bounds check hint to compiler; see golang.org/issue/14808
459 z[3] = uint64(binary.BigEndian.Uint32(in[0:4]))
460 z[2] = binary.BigEndian.Uint64(in[4:12])
461 z[1] = binary.BigEndian.Uint64(in[12:20])
462 z[0] = binary.BigEndian.Uint64(in[20:28])
463 return z
464}
465
466// SetBytes29 sets z from a 29-byte big-endian slice and returns z.
467// Panics if input is shorter than 29 bytes.
468func (z *Uint) SetBytes29(in []byte) *Uint {
469 _ = in[28] // bounds check hint to compiler; see golang.org/issue/14808
470 z[3] = bigEndianUint40(in[0:5])
471 z[2] = binary.BigEndian.Uint64(in[5:13])
472 z[1] = binary.BigEndian.Uint64(in[13:21])
473 z[0] = binary.BigEndian.Uint64(in[21:29])
474 return z
475}
476
477// SetBytes30 sets z from a 30-byte big-endian slice and returns z.
478// Panics if input is shorter than 30 bytes.
479func (z *Uint) SetBytes30(in []byte) *Uint {
480 _ = in[29] // bounds check hint to compiler; see golang.org/issue/14808
481 z[3] = bigEndianUint48(in[0:6])
482 z[2] = binary.BigEndian.Uint64(in[6:14])
483 z[1] = binary.BigEndian.Uint64(in[14:22])
484 z[0] = binary.BigEndian.Uint64(in[22:30])
485 return z
486}
487
488// SetBytes31 sets z from a 31-byte big-endian slice and returns z.
489// Panics if input is shorter than 31 bytes.
490func (z *Uint) SetBytes31(in []byte) *Uint {
491 _ = in[30] // bounds check hint to compiler; see golang.org/issue/14808
492 z[3] = bigEndianUint56(in[0:7])
493 z[2] = binary.BigEndian.Uint64(in[7:15])
494 z[1] = binary.BigEndian.Uint64(in[15:23])
495 z[0] = binary.BigEndian.Uint64(in[23:31])
496 return z
497}
498
499// SetBytes32 sets z from a 32-byte big-endian slice and returns z.
500// Panics if input is shorter than 32 bytes.
501func (z *Uint) SetBytes32(in []byte) *Uint {
502 _ = in[31] // bounds check hint to compiler; see golang.org/issue/14808
503 z[3] = binary.BigEndian.Uint64(in[0:8])
504 z[2] = binary.BigEndian.Uint64(in[8:16])
505 z[1] = binary.BigEndian.Uint64(in[16:24])
506 z[0] = binary.BigEndian.Uint64(in[24:32])
507 return z
508}
509
510// Utility methods that are "missing" among the bigEndian.UintXX methods.
511
512// bigEndianUint40 returns the uint64 value represented by the 5 bytes in big-endian order.
513func bigEndianUint40(b []byte) uint64 {
514 _ = b[4] // bounds check hint to compiler; see golang.org/issue/14808
515 return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 |
516 uint64(b[0])<<32
517}
518
519// bigEndianUint56 returns the uint64 value represented by the 7 bytes in big-endian order.
520func bigEndianUint56(b []byte) uint64 {
521 _ = b[6] // bounds check hint to compiler; see golang.org/issue/14808
522 return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | uint64(b[3])<<24 |
523 uint64(b[2])<<32 | uint64(b[1])<<40 | uint64(b[0])<<48
524}
525
526// bigEndianUint48 returns the uint64 value represented by the 6 bytes in big-endian order.
527func bigEndianUint48(b []byte) uint64 {
528 _ = b[5] // bounds check hint to compiler; see golang.org/issue/14808
529 return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 |
530 uint64(b[1])<<32 | uint64(b[0])<<40
531}