conversion.gno
16.50 Kb ยท 532 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
100// ToString returns the decimal string representation of z.
101// Returns an empty string if z is nil. This method doesn't exist in holiman's uint256.
102func (z *Uint) ToString() string {
103 if z == nil {
104 return ""
105 }
106
107 return z.Dec()
108}
109
110// SetBytes interprets buf as a big-endian unsigned integer and sets z to that value.
111// If buf is larger than 32 bytes, uses only the last 32 bytes. Returns z.
112func (z *Uint) SetBytes(buf []byte) *Uint {
113 switch l := len(buf); l {
114 case 0:
115 z.Clear()
116 case 1:
117 z.SetBytes1(buf)
118 case 2:
119 z.SetBytes2(buf)
120 case 3:
121 z.SetBytes3(buf)
122 case 4:
123 z.SetBytes4(buf)
124 case 5:
125 z.SetBytes5(buf)
126 case 6:
127 z.SetBytes6(buf)
128 case 7:
129 z.SetBytes7(buf)
130 case 8:
131 z.SetBytes8(buf)
132 case 9:
133 z.SetBytes9(buf)
134 case 10:
135 z.SetBytes10(buf)
136 case 11:
137 z.SetBytes11(buf)
138 case 12:
139 z.SetBytes12(buf)
140 case 13:
141 z.SetBytes13(buf)
142 case 14:
143 z.SetBytes14(buf)
144 case 15:
145 z.SetBytes15(buf)
146 case 16:
147 z.SetBytes16(buf)
148 case 17:
149 z.SetBytes17(buf)
150 case 18:
151 z.SetBytes18(buf)
152 case 19:
153 z.SetBytes19(buf)
154 case 20:
155 z.SetBytes20(buf)
156 case 21:
157 z.SetBytes21(buf)
158 case 22:
159 z.SetBytes22(buf)
160 case 23:
161 z.SetBytes23(buf)
162 case 24:
163 z.SetBytes24(buf)
164 case 25:
165 z.SetBytes25(buf)
166 case 26:
167 z.SetBytes26(buf)
168 case 27:
169 z.SetBytes27(buf)
170 case 28:
171 z.SetBytes28(buf)
172 case 29:
173 z.SetBytes29(buf)
174 case 30:
175 z.SetBytes30(buf)
176 case 31:
177 z.SetBytes31(buf)
178 default:
179 z.SetBytes32(buf[l-32:])
180 }
181 return z
182}
183
184// SetBytes1 sets z from a 1-byte big-endian slice and returns z.
185// Panics if input is shorter than 1 byte.
186func (z *Uint) SetBytes1(in []byte) *Uint {
187 z[3], z[2], z[1] = 0, 0, 0
188 z[0] = uint64(in[0])
189 return z
190}
191
192// SetBytes2 sets z from a 2-byte big-endian slice and returns z.
193// Panics if input is shorter than 2 bytes.
194func (z *Uint) SetBytes2(in []byte) *Uint {
195 _ = in[1] // bounds check hint to compiler; see golang.org/issue/14808
196 z[3], z[2], z[1] = 0, 0, 0
197 z[0] = uint64(binary.BigEndian.Uint16(in[0:2]))
198 return z
199}
200
201// SetBytes3 sets z from a 3-byte big-endian slice and returns z.
202// Panics if input is shorter than 3 bytes.
203func (z *Uint) SetBytes3(in []byte) *Uint {
204 _ = in[2] // bounds check hint to compiler; see golang.org/issue/14808
205 z[3], z[2], z[1] = 0, 0, 0
206 z[0] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
207 return z
208}
209
210// SetBytes4 sets z from a 4-byte big-endian slice and returns z.
211// Panics if input is shorter than 4 bytes.
212func (z *Uint) SetBytes4(in []byte) *Uint {
213 _ = in[3] // bounds check hint to compiler; see golang.org/issue/14808
214 z[3], z[2], z[1] = 0, 0, 0
215 z[0] = uint64(binary.BigEndian.Uint32(in[0:4]))
216 return z
217}
218
219// SetBytes5 sets z from a 5-byte big-endian slice and returns z.
220// Panics if input is shorter than 5 bytes.
221func (z *Uint) SetBytes5(in []byte) *Uint {
222 _ = in[4] // bounds check hint to compiler; see golang.org/issue/14808
223 z[3], z[2], z[1] = 0, 0, 0
224 z[0] = bigEndianUint40(in[0:5])
225 return z
226}
227
228// SetBytes6 sets z from a 6-byte big-endian slice and returns z.
229// Panics if input is shorter than 6 bytes.
230func (z *Uint) SetBytes6(in []byte) *Uint {
231 _ = in[5] // bounds check hint to compiler; see golang.org/issue/14808
232 z[3], z[2], z[1] = 0, 0, 0
233 z[0] = bigEndianUint48(in[0:6])
234 return z
235}
236
237// SetBytes7 sets z from a 7-byte big-endian slice and returns z.
238// Panics if input is shorter than 7 bytes.
239func (z *Uint) SetBytes7(in []byte) *Uint {
240 _ = in[6] // bounds check hint to compiler; see golang.org/issue/14808
241 z[3], z[2], z[1] = 0, 0, 0
242 z[0] = bigEndianUint56(in[0:7])
243 return z
244}
245
246// SetBytes8 sets z from an 8-byte big-endian slice and returns z.
247// Panics if input is shorter than 8 bytes.
248func (z *Uint) SetBytes8(in []byte) *Uint {
249 _ = in[7] // bounds check hint to compiler; see golang.org/issue/14808
250 z[3], z[2], z[1] = 0, 0, 0
251 z[0] = binary.BigEndian.Uint64(in[0:8])
252 return z
253}
254
255// SetBytes9 sets z from a 9-byte big-endian slice and returns z.
256// Panics if input is shorter than 9 bytes.
257func (z *Uint) SetBytes9(in []byte) *Uint {
258 _ = in[8] // bounds check hint to compiler; see golang.org/issue/14808
259 z[3], z[2] = 0, 0
260 z[1] = uint64(in[0])
261 z[0] = binary.BigEndian.Uint64(in[1:9])
262 return z
263}
264
265// SetBytes10 sets z from a 10-byte big-endian slice and returns z.
266// Panics if input is shorter than 10 bytes.
267func (z *Uint) SetBytes10(in []byte) *Uint {
268 _ = in[9] // bounds check hint to compiler; see golang.org/issue/14808
269 z[3], z[2] = 0, 0
270 z[1] = uint64(binary.BigEndian.Uint16(in[0:2]))
271 z[0] = binary.BigEndian.Uint64(in[2:10])
272 return z
273}
274
275// SetBytes11 sets z from an 11-byte big-endian slice and returns z.
276// Panics if input is shorter than 11 bytes.
277func (z *Uint) SetBytes11(in []byte) *Uint {
278 _ = in[10] // bounds check hint to compiler; see golang.org/issue/14808
279 z[3], z[2] = 0, 0
280 z[1] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
281 z[0] = binary.BigEndian.Uint64(in[3:11])
282 return z
283}
284
285// SetBytes12 sets z from a 12-byte big-endian slice and returns z.
286// Panics if input is shorter than 12 bytes.
287func (z *Uint) SetBytes12(in []byte) *Uint {
288 _ = in[11] // bounds check hint to compiler; see golang.org/issue/14808
289 z[3], z[2] = 0, 0
290 z[1] = uint64(binary.BigEndian.Uint32(in[0:4]))
291 z[0] = binary.BigEndian.Uint64(in[4:12])
292 return z
293}
294
295// SetBytes13 sets z from a 13-byte big-endian slice and returns z.
296// Panics if input is shorter than 13 bytes.
297func (z *Uint) SetBytes13(in []byte) *Uint {
298 _ = in[12] // bounds check hint to compiler; see golang.org/issue/14808
299 z[3], z[2] = 0, 0
300 z[1] = bigEndianUint40(in[0:5])
301 z[0] = binary.BigEndian.Uint64(in[5:13])
302 return z
303}
304
305// SetBytes14 sets z from a 14-byte big-endian slice and returns z.
306// Panics if input is shorter than 14 bytes.
307func (z *Uint) SetBytes14(in []byte) *Uint {
308 _ = in[13] // bounds check hint to compiler; see golang.org/issue/14808
309 z[3], z[2] = 0, 0
310 z[1] = bigEndianUint48(in[0:6])
311 z[0] = binary.BigEndian.Uint64(in[6:14])
312 return z
313}
314
315// SetBytes15 sets z from a 15-byte big-endian slice and returns z.
316// Panics if input is shorter than 15 bytes.
317func (z *Uint) SetBytes15(in []byte) *Uint {
318 _ = in[14] // bounds check hint to compiler; see golang.org/issue/14808
319 z[3], z[2] = 0, 0
320 z[1] = bigEndianUint56(in[0:7])
321 z[0] = binary.BigEndian.Uint64(in[7:15])
322 return z
323}
324
325// SetBytes16 sets z from a 16-byte big-endian slice and returns z.
326// Panics if input is shorter than 16 bytes.
327func (z *Uint) SetBytes16(in []byte) *Uint {
328 _ = in[15] // bounds check hint to compiler; see golang.org/issue/14808
329 z[3], z[2] = 0, 0
330 z[1] = binary.BigEndian.Uint64(in[0:8])
331 z[0] = binary.BigEndian.Uint64(in[8:16])
332 return z
333}
334
335// SetBytes17 sets z from a 17-byte big-endian slice and returns z.
336// Panics if input is shorter than 17 bytes.
337func (z *Uint) SetBytes17(in []byte) *Uint {
338 _ = in[16] // bounds check hint to compiler; see golang.org/issue/14808
339 z[3] = 0
340 z[2] = uint64(in[0])
341 z[1] = binary.BigEndian.Uint64(in[1:9])
342 z[0] = binary.BigEndian.Uint64(in[9:17])
343 return z
344}
345
346// SetBytes18 sets z from an 18-byte big-endian slice and returns z.
347// Panics if input is shorter than 18 bytes.
348func (z *Uint) SetBytes18(in []byte) *Uint {
349 _ = in[17] // bounds check hint to compiler; see golang.org/issue/14808
350 z[3] = 0
351 z[2] = uint64(binary.BigEndian.Uint16(in[0:2]))
352 z[1] = binary.BigEndian.Uint64(in[2:10])
353 z[0] = binary.BigEndian.Uint64(in[10:18])
354 return z
355}
356
357// SetBytes19 sets z from a 19-byte big-endian slice and returns z.
358// Panics if input is shorter than 19 bytes.
359func (z *Uint) SetBytes19(in []byte) *Uint {
360 _ = in[18] // bounds check hint to compiler; see golang.org/issue/14808
361 z[3] = 0
362 z[2] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
363 z[1] = binary.BigEndian.Uint64(in[3:11])
364 z[0] = binary.BigEndian.Uint64(in[11:19])
365 return z
366}
367
368// SetBytes20 sets z from a 20-byte big-endian slice and returns z.
369// Panics if input is shorter than 20 bytes.
370func (z *Uint) SetBytes20(in []byte) *Uint {
371 _ = in[19] // bounds check hint to compiler; see golang.org/issue/14808
372 z[3] = 0
373 z[2] = uint64(binary.BigEndian.Uint32(in[0:4]))
374 z[1] = binary.BigEndian.Uint64(in[4:12])
375 z[0] = binary.BigEndian.Uint64(in[12:20])
376 return z
377}
378
379// SetBytes21 sets z from a 21-byte big-endian slice and returns z.
380// Panics if input is shorter than 21 bytes.
381func (z *Uint) SetBytes21(in []byte) *Uint {
382 _ = in[20] // bounds check hint to compiler; see golang.org/issue/14808
383 z[3] = 0
384 z[2] = bigEndianUint40(in[0:5])
385 z[1] = binary.BigEndian.Uint64(in[5:13])
386 z[0] = binary.BigEndian.Uint64(in[13:21])
387 return z
388}
389
390// SetBytes22 sets z from a 22-byte big-endian slice and returns z.
391// Panics if input is shorter than 22 bytes.
392func (z *Uint) SetBytes22(in []byte) *Uint {
393 _ = in[21] // bounds check hint to compiler; see golang.org/issue/14808
394 z[3] = 0
395 z[2] = bigEndianUint48(in[0:6])
396 z[1] = binary.BigEndian.Uint64(in[6:14])
397 z[0] = binary.BigEndian.Uint64(in[14:22])
398 return z
399}
400
401// SetBytes23 sets z from a 23-byte big-endian slice and returns z.
402// Panics if input is shorter than 23 bytes.
403func (z *Uint) SetBytes23(in []byte) *Uint {
404 _ = in[22] // bounds check hint to compiler; see golang.org/issue/14808
405 z[3] = 0
406 z[2] = bigEndianUint56(in[0:7])
407 z[1] = binary.BigEndian.Uint64(in[7:15])
408 z[0] = binary.BigEndian.Uint64(in[15:23])
409 return z
410}
411
412// SetBytes24 sets z from a 24-byte big-endian slice and returns z.
413// Panics if input is shorter than 24 bytes.
414func (z *Uint) SetBytes24(in []byte) *Uint {
415 _ = in[23] // bounds check hint to compiler; see golang.org/issue/14808
416 z[3] = 0
417 z[2] = binary.BigEndian.Uint64(in[0:8])
418 z[1] = binary.BigEndian.Uint64(in[8:16])
419 z[0] = binary.BigEndian.Uint64(in[16:24])
420 return z
421}
422
423// SetBytes25 sets z from a 25-byte big-endian slice and returns z.
424// Panics if input is shorter than 25 bytes.
425func (z *Uint) SetBytes25(in []byte) *Uint {
426 _ = in[24] // bounds check hint to compiler; see golang.org/issue/14808
427 z[3] = uint64(in[0])
428 z[2] = binary.BigEndian.Uint64(in[1:9])
429 z[1] = binary.BigEndian.Uint64(in[9:17])
430 z[0] = binary.BigEndian.Uint64(in[17:25])
431 return z
432}
433
434// SetBytes26 sets z from a 26-byte big-endian slice and returns z.
435// Panics if input is shorter than 26 bytes.
436func (z *Uint) SetBytes26(in []byte) *Uint {
437 _ = in[25] // bounds check hint to compiler; see golang.org/issue/14808
438 z[3] = uint64(binary.BigEndian.Uint16(in[0:2]))
439 z[2] = binary.BigEndian.Uint64(in[2:10])
440 z[1] = binary.BigEndian.Uint64(in[10:18])
441 z[0] = binary.BigEndian.Uint64(in[18:26])
442 return z
443}
444
445// SetBytes27 sets z from a 27-byte big-endian slice and returns z.
446// Panics if input is shorter than 27 bytes.
447func (z *Uint) SetBytes27(in []byte) *Uint {
448 _ = in[26] // bounds check hint to compiler; see golang.org/issue/14808
449 z[3] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16
450 z[2] = binary.BigEndian.Uint64(in[3:11])
451 z[1] = binary.BigEndian.Uint64(in[11:19])
452 z[0] = binary.BigEndian.Uint64(in[19:27])
453 return z
454}
455
456// SetBytes28 sets z from a 28-byte big-endian slice and returns z.
457// Panics if input is shorter than 28 bytes.
458func (z *Uint) SetBytes28(in []byte) *Uint {
459 _ = in[27] // bounds check hint to compiler; see golang.org/issue/14808
460 z[3] = uint64(binary.BigEndian.Uint32(in[0:4]))
461 z[2] = binary.BigEndian.Uint64(in[4:12])
462 z[1] = binary.BigEndian.Uint64(in[12:20])
463 z[0] = binary.BigEndian.Uint64(in[20:28])
464 return z
465}
466
467// SetBytes29 sets z from a 29-byte big-endian slice and returns z.
468// Panics if input is shorter than 29 bytes.
469func (z *Uint) SetBytes29(in []byte) *Uint {
470 _ = in[28] // bounds check hint to compiler; see golang.org/issue/14808
471 z[3] = bigEndianUint40(in[0:5])
472 z[2] = binary.BigEndian.Uint64(in[5:13])
473 z[1] = binary.BigEndian.Uint64(in[13:21])
474 z[0] = binary.BigEndian.Uint64(in[21:29])
475 return z
476}
477
478// SetBytes30 sets z from a 30-byte big-endian slice and returns z.
479// Panics if input is shorter than 30 bytes.
480func (z *Uint) SetBytes30(in []byte) *Uint {
481 _ = in[29] // bounds check hint to compiler; see golang.org/issue/14808
482 z[3] = bigEndianUint48(in[0:6])
483 z[2] = binary.BigEndian.Uint64(in[6:14])
484 z[1] = binary.BigEndian.Uint64(in[14:22])
485 z[0] = binary.BigEndian.Uint64(in[22:30])
486 return z
487}
488
489// SetBytes31 sets z from a 31-byte big-endian slice and returns z.
490// Panics if input is shorter than 31 bytes.
491func (z *Uint) SetBytes31(in []byte) *Uint {
492 _ = in[30] // bounds check hint to compiler; see golang.org/issue/14808
493 z[3] = bigEndianUint56(in[0:7])
494 z[2] = binary.BigEndian.Uint64(in[7:15])
495 z[1] = binary.BigEndian.Uint64(in[15:23])
496 z[0] = binary.BigEndian.Uint64(in[23:31])
497 return z
498}
499
500// SetBytes32 sets z from a 32-byte big-endian slice and returns z.
501// Panics if input is shorter than 32 bytes.
502func (z *Uint) SetBytes32(in []byte) *Uint {
503 _ = in[31] // bounds check hint to compiler; see golang.org/issue/14808
504 z[3] = binary.BigEndian.Uint64(in[0:8])
505 z[2] = binary.BigEndian.Uint64(in[8:16])
506 z[1] = binary.BigEndian.Uint64(in[16:24])
507 z[0] = binary.BigEndian.Uint64(in[24:32])
508 return z
509}
510
511// Utility methods that are "missing" among the bigEndian.UintXX methods.
512
513// bigEndianUint40 returns the uint64 value represented by the 5 bytes in big-endian order.
514func bigEndianUint40(b []byte) uint64 {
515 _ = b[4] // bounds check hint to compiler; see golang.org/issue/14808
516 return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 |
517 uint64(b[0])<<32
518}
519
520// bigEndianUint56 returns the uint64 value represented by the 7 bytes in big-endian order.
521func bigEndianUint56(b []byte) uint64 {
522 _ = b[6] // bounds check hint to compiler; see golang.org/issue/14808
523 return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | uint64(b[3])<<24 |
524 uint64(b[2])<<32 | uint64(b[1])<<40 | uint64(b[0])<<48
525}
526
527// bigEndianUint48 returns the uint64 value represented by the 6 bytes in big-endian order.
528func bigEndianUint48(b []byte) uint64 {
529 _ = b[5] // bounds check hint to compiler; see golang.org/issue/14808
530 return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 |
531 uint64(b[1])<<32 | uint64(b[0])<<40
532}