1use std::mem;
2
3use cosmwasm_std::{Int128, Int64, Uint128, Uint64};
4
5pub trait IntKey: Sized + Copy {
10 type Buf: AsRef<[u8]> + AsMut<[u8]> + Into<Vec<u8>> + Default;
11
12 fn to_cw_bytes(&self) -> Self::Buf;
13 fn from_cw_bytes(bytes: Self::Buf) -> Self;
14}
15
16macro_rules! cw_uint_keys {
17 (for $($t:ty),+) => {
18 $(impl IntKey for $t {
19 type Buf = [u8; mem::size_of::<$t>()];
20
21 #[inline]
22 fn to_cw_bytes(&self) -> Self::Buf {
23 self.to_be_bytes()
24 }
25
26 #[inline]
27 fn from_cw_bytes(bytes: Self::Buf) -> Self {
28 Self::from_be_bytes(bytes)
29 }
30 })*
31 }
32}
33
34cw_uint_keys!(for u8, u16, u32, u64, u128);
35
36macro_rules! cw_int_keys {
37 (for $($t:ty, $ut:ty),+) => {
38 $(impl IntKey for $t {
39 type Buf = [u8; mem::size_of::<$t>()];
40
41 #[inline]
42 fn to_cw_bytes(&self) -> Self::Buf {
43 (*self as $ut ^ <$t>::MIN as $ut).to_be_bytes()
44 }
45
46 #[inline]
47 fn from_cw_bytes(bytes: Self::Buf) -> Self {
48 (Self::from_be_bytes(bytes) as $ut ^ <$t>::MIN as $ut) as _
49 }
50 })*
51 }
52}
53
54cw_int_keys!(for i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
55
56macro_rules! cw_uint_std_keys {
57 (for $($t:ty),+) => {
58 $(impl IntKey for $t {
59 type Buf = [u8; mem::size_of::<$t>()];
60
61 #[inline]
62 fn to_cw_bytes(&self) -> Self::Buf {
63 self.to_be_bytes()
64 }
65
66 #[inline]
67 fn from_cw_bytes(bytes: Self::Buf) -> Self {
68 Self::new(IntKey::from_cw_bytes(bytes))
69 }
70 })*
71 }
72}
73
74cw_uint_std_keys!(for Uint64, Uint128);
75
76macro_rules! cw_int_std_keys {
77 (for $($t:ty),+) => {
78 $(impl IntKey for $t {
79 type Buf = [u8; mem::size_of::<$t>()];
80
81 #[inline]
82 fn to_cw_bytes(&self) -> Self::Buf {
83 let mut bytes = self.to_be_bytes();
84 bytes[0] ^= 0x80;
85 bytes
86 }
87
88 #[inline]
89 fn from_cw_bytes(bytes: Self::Buf) -> Self {
90 Self::new(IntKey::from_cw_bytes(bytes))
91 }
92 })*
93 }
94}
95
96cw_int_std_keys!(for Int64, Int128);
97
98#[cfg(test)]
99mod test {
100 use super::*;
101
102 #[test]
103 fn x8_int_key_works() {
104 assert_eq!(0x42u8.to_cw_bytes(), [0x42]);
105 assert_eq!(0x42i8.to_cw_bytes(), [0xc2]);
106 assert_eq!((-0x3ei8).to_cw_bytes(), [0x42]);
107 }
108
109 #[test]
110 fn x16_int_key_works() {
111 assert_eq!(0x4243u16.to_cw_bytes(), [0x42, 0x43]);
112 assert_eq!(0x4243i16.to_cw_bytes(), [0xc2, 0x43]);
113 assert_eq!((-0x3dbdi16).to_cw_bytes(), [0x42, 0x43]);
114 }
115
116 #[test]
117 fn x32_int_key_works() {
118 assert_eq!(0x424344u32.to_cw_bytes(), [0x00, 0x42, 0x43, 0x44]);
119 assert_eq!(0x424344i32.to_cw_bytes(), [0x80, 0x42, 0x43, 0x44]);
120 assert_eq!((-0x7fbdbcbci32).to_cw_bytes(), [0x00, 0x42, 0x43, 0x44]);
121 }
122
123 #[test]
124 fn x64_int_key_works() {
125 assert_eq!(
126 0x42434445u64.to_cw_bytes(),
127 [0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
128 );
129 assert_eq!(
130 0x42434445i64.to_cw_bytes(),
131 [0x80, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
132 );
133 assert_eq!(
134 (-0x7fffffffbdbcbbbbi64).to_cw_bytes(),
135 [0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44, 0x45]
136 );
137 }
138
139 #[test]
140 fn x128_int_key_works() {
141 assert_eq!(
142 0x4243444546u128.to_cw_bytes(),
143 [
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
145 0x45, 0x46
146 ]
147 );
148 assert_eq!(
149 0x4243444546i128.to_cw_bytes(),
150 [
151 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
152 0x45, 0x46
153 ]
154 );
155 assert_eq!(
156 (-0x7fffffffffffffffffffffbdbcbbbabai128).to_cw_bytes(),
157 [
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x43, 0x44,
159 0x45, 0x46
160 ]
161 );
162 }
163
164 #[test]
165 fn unsigned_int_key_order() {
166 assert!(0u32.to_cw_bytes() < 652u32.to_cw_bytes());
167 }
168
169 #[test]
170 fn signed_int_key_order() {
171 assert!((-321i32).to_cw_bytes() < 0i32.to_cw_bytes());
172 assert!(0i32.to_cw_bytes() < 652i32.to_cw_bytes());
173 }
174}