codec.gno
3.98 Kb · 146 lines
1package utils
2
3import (
4 u256 "gno.land/p/gnoswap/uint256/v1"
5 "gno.land/p/nt/ufmt/v0"
6)
7
8// EncodeUint16 converts a uint16 to a fixed-width two-byte big-endian string.
9//
10// Parameters:
11// - value: Unsigned 16-bit integer to encode.
12//
13// Returns:
14// - encoded: Exactly two bytes in big-endian order; lexicographic order matches numeric order.
15func EncodeUint16(value uint16) string {
16 var buf [2]byte
17 buf[0] = byte(value >> 8)
18 buf[1] = byte(value)
19 return string(buf[:])
20}
21
22// DecodeUint16 decodes a fixed-width two-byte big-endian string.
23//
24// Parameters:
25// - key: Exactly two encoded bytes, with the most-significant byte first.
26//
27// Returns:
28// - value: The uint16 represented by key.
29//
30// Panics if key is not exactly two bytes long.
31func DecodeUint16(key string) uint16 {
32 if len(key) != 2 {
33 panic(ufmt.Sprintf("invalid uint16 key length: %d", len(key)))
34 }
35 return uint16(key[0])<<8 | uint16(key[1])
36}
37
38// EncodeInt32 converts an int32 to a fixed-width four-byte big-endian string.
39// Flipping the sign bit makes lexicographic order match signed numeric order.
40//
41// Parameters:
42// - value: Signed 32-bit integer to encode.
43//
44// Returns:
45// - encoded: Exactly four order-preserving big-endian bytes.
46func EncodeInt32(value int32) string {
47 ordered := uint32(value) ^ (uint32(1) << 31)
48 var buf [4]byte
49 buf[0] = byte(ordered >> 24)
50 buf[1] = byte(ordered >> 16)
51 buf[2] = byte(ordered >> 8)
52 buf[3] = byte(ordered)
53 return string(buf[:])
54}
55
56// DecodeInt32 decodes a four-byte order-preserving big-endian string.
57//
58// Parameters:
59// - key: Exactly four bytes produced by EncodeInt32.
60//
61// Returns:
62// - value: The signed int32 recovered after reversing the sign-bit transform.
63//
64// Panics if key is not exactly four bytes long.
65func DecodeInt32(key string) int32 {
66 if len(key) != 4 {
67 panic(ufmt.Sprintf("invalid int32 key length: %d", len(key)))
68 }
69 ordered := uint32(key[0])<<24 |
70 uint32(key[1])<<16 |
71 uint32(key[2])<<8 |
72 uint32(key[3])
73 return int32(ordered ^ (uint32(1) << 31))
74}
75
76// EncodeUint64 converts a uint64 to a fixed-width eight-byte big-endian string.
77//
78// Parameters:
79// - value: Unsigned 64-bit integer to encode.
80//
81// Returns:
82// - encoded: Exactly eight bytes in big-endian order.
83func EncodeUint64(value uint64) string {
84 var buf [8]byte
85 buf[0] = byte(value >> 56)
86 buf[1] = byte(value >> 48)
87 buf[2] = byte(value >> 40)
88 buf[3] = byte(value >> 32)
89 buf[4] = byte(value >> 24)
90 buf[5] = byte(value >> 16)
91 buf[6] = byte(value >> 8)
92 buf[7] = byte(value)
93 return string(buf[:])
94}
95
96// DecodeUint64 decodes a fixed-width eight-byte big-endian string.
97//
98// Parameters:
99// - key: Exactly eight encoded bytes, with the most-significant byte first.
100//
101// Returns:
102// - value: The uint64 represented by key.
103//
104// Panics if key is not exactly eight bytes long.
105func DecodeUint64(key string) uint64 {
106 if len(key) != 8 {
107 panic(ufmt.Sprintf("invalid uint64 key length: %d", len(key)))
108 }
109 return uint64(key[0])<<56 |
110 uint64(key[1])<<48 |
111 uint64(key[2])<<40 |
112 uint64(key[3])<<32 |
113 uint64(key[4])<<24 |
114 uint64(key[5])<<16 |
115 uint64(key[6])<<8 |
116 uint64(key[7])
117}
118
119// EncodeUint256 converts a 256-bit unsigned integer to a fixed-width 32-byte
120// big-endian string, emitting the most-significant limb first.
121//
122// Parameters:
123// - value: Non-nil *u256.Uint value to encode.
124//
125// Returns:
126// - encoded: Exactly 32 big-endian bytes representing value.
127func EncodeUint256(value *u256.Uint) string {
128 return EncodeUint64(value[3]) + EncodeUint64(value[2]) +
129 EncodeUint64(value[1]) + EncodeUint64(value[0])
130}
131
132// DecodeUint256 decodes a fixed-width 32-byte big-endian uint256 encoding.
133//
134// Parameters:
135// - encoded: Exactly 32 bytes containing the most-significant byte first.
136//
137// Returns:
138// - value: A new *u256.Uint populated from encoded.
139//
140// Panics if encoded is not exactly 32 bytes long.
141func DecodeUint256(encoded string) *u256.Uint {
142 if len(encoded) != 32 {
143 panic(ufmt.Sprintf("invalid uint256 encoding length: %d", len(encoded)))
144 }
145 return u256.Zero().SetBytes([]byte(encoded))
146}