Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}