Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}