1use cosmwasm_schema::cw_serde;
2use cosmwasm_std::{HexBinary, StdError, StdResult};
3use cw_storage_plus::{Key, KeyDeserialize, Prefixer, PrimaryKey};
4use std::fmt;
5use std::ops::{Deref, DerefMut};
6
7#[cw_serde]
9pub struct SlashingRequestId(pub HexBinary);
10
11impl SlashingRequestId {
12 pub fn to_hex(&self) -> String {
14 self.0.to_hex()
15 }
16
17 pub fn from_hex(hex: &str) -> StdResult<Self> {
19 let bytes = HexBinary::from_hex(hex)?;
20 if bytes.len() != 32 {
21 return Err(StdError::generic_err("Invalid hex length"));
22 }
23 Ok(SlashingRequestId(bytes))
24 }
25}
26
27impl fmt::Display for SlashingRequestId {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(f, "{}", self.0.to_hex())
30 }
31}
32
33impl Deref for SlashingRequestId {
34 type Target = HexBinary;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39}
40
41impl DerefMut for SlashingRequestId {
42 fn deref_mut(&mut self) -> &mut Self::Target {
43 &mut self.0
44 }
45}
46
47impl From<HexBinary> for SlashingRequestId {
48 fn from(bytes: HexBinary) -> Self {
49 Self(bytes)
50 }
51}
52
53impl From<[u8; 32]> for SlashingRequestId {
54 fn from(bytes: [u8; 32]) -> Self {
55 Self(HexBinary::from(bytes))
56 }
57}
58
59impl PrimaryKey<'_> for SlashingRequestId {
60 type Prefix = ();
61 type SubPrefix = ();
62 type Suffix = Self;
63 type SuperSuffix = Self;
64
65 fn key(&self) -> Vec<Key> {
66 vec![Key::Ref(self.0.as_slice())]
67 }
68}
69
70impl Prefixer<'_> for SlashingRequestId {
71 fn prefix(&self) -> Vec<Key> {
72 vec![Key::Ref(self.0.as_slice())]
73 }
74}
75
76impl KeyDeserialize for SlashingRequestId {
77 type Output = Self;
78
79 const KEY_ELEMS: u16 = 1;
80
81 #[inline(always)]
82 fn from_vec(value: Vec<u8>) -> StdResult<Self::Output> {
83 Ok(SlashingRequestId(HexBinary::from(value)))
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use cosmwasm_std::testing::MockStorage;
91 use cosmwasm_std::Addr;
92 use cw_storage_plus::Map;
93
94 mod slashing_request_id {
95 use super::*;
96
97 #[test]
98 fn test_from_hex_valid() {
99 let hex = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20";
101 let result = SlashingRequestId::from_hex(hex);
102 assert!(result.is_ok());
103 let id = result.unwrap();
104 assert_eq!(id.to_hex(), hex);
105 }
106
107 #[test]
108 fn test_from_hex_invalid_format() {
109 let result = SlashingRequestId::from_hex("not a hex string");
111 assert!(result.is_err());
112
113 let result = SlashingRequestId::from_hex("0102030405");
115 assert!(result.is_err());
116
117 let result = SlashingRequestId::from_hex(
119 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021",
120 );
121 assert!(result.is_err());
122
123 let result = SlashingRequestId::from_hex("0x0102030405060708090a0b0c0d0e0f");
125 assert!(result.is_err());
126 }
127
128 #[test]
129 fn test_to_hex() {
130 let hexbinary = HexBinary::from_hex(
131 "0000000000000000000000000000000000000000000000000000000000000000",
132 )
133 .unwrap();
134 let id = SlashingRequestId::from(hexbinary.clone());
135 assert_eq!(id.to_hex(), hexbinary.to_hex());
136 assert_eq!(
137 id.to_hex(),
138 "0000000000000000000000000000000000000000000000000000000000000000"
139 );
140
141 let bytes = [
142 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
143 24, 25, 26, 27, 28, 29, 30, 31, 32,
144 ];
145 let hexbinary = HexBinary::from(bytes);
146 let id = SlashingRequestId::from(bytes);
147 assert_eq!(id.to_hex(), hexbinary.to_hex());
148 assert_eq!(
149 id.to_hex(),
150 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
151 );
152 }
153
154 #[test]
155 fn test_display_implementation() {
156 let hex_string = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20";
157 let id = SlashingRequestId::from_hex(hex_string).unwrap();
158 assert_eq!(format!("{}", id), hex_string);
159 assert_eq!(
160 id.to_string(),
161 "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20"
162 );
163 }
164
165 #[test]
166 fn test_from_implementations() {
167 let bytes = [
169 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
170 24, 25, 26, 27, 28, 29, 30, 31, 32,
171 ];
172 let id = SlashingRequestId::from(bytes);
173 assert_eq!(id.0.as_slice(), &bytes);
174
175 let hex_binary = HexBinary::from(bytes);
177 let id = SlashingRequestId::from(hex_binary.clone());
178 assert_eq!(id.0, hex_binary);
179 }
180
181 #[test]
182 fn test_storage_implementations() {
183 let hex_string1 = "5808db357efe7b2a8c61de8c772b7e09e676a0bdb880528acfdc259c8cd1840f";
184 let hex_string2 = "3dc9b61793974139e89c1fd40ba1c8da459a8fa387d8d6afb32e6386e6b42146";
185 let id1 = SlashingRequestId::from_hex(hex_string1).unwrap();
186 let id2 = SlashingRequestId::from_hex(hex_string2).unwrap();
187
188 let map: Map<&SlashingRequestId, u64> = Map::new("test_map");
190 let mut storage = MockStorage::new();
191
192 map.save(&mut storage, &id1, &42u64).unwrap();
194 map.save(&mut storage, &id2, &84u64).unwrap();
195
196 let value1 = map.load(&storage, &id1).unwrap();
198 let value2 = map.load(&storage, &id2).unwrap();
199
200 assert_eq!(value1, 42u64);
201 assert_eq!(value2, 84u64);
202
203 let map: Map<SlashingRequestId, u64> = Map::new("test_map");
205 let mut storage = MockStorage::new();
206
207 map.save(&mut storage, id1.clone(), &42u64).unwrap();
209 map.save(&mut storage, id2.clone(), &84u64).unwrap();
210
211 let value1 = map.load(&storage, id1).unwrap();
213 let value2 = map.load(&storage, id2).unwrap();
214
215 assert_eq!(value1, 42u64);
216 assert_eq!(value2, 84u64);
217 }
218
219 #[test]
220 fn test_storage_implementations_with_prefix() {
221 let hex_string1 = "5808db357efe7b2a8c61de8c772b7e09e676a0bdb880528acfdc259c8cd1840f";
223 let hex_string2 = "3dc9b61793974139e89c1fd40ba1c8da459a8fa387d8d6afb32e6386e6b42146";
224 let id1 = SlashingRequestId::from_hex(hex_string1).unwrap();
225 let id2 = SlashingRequestId::from_hex(hex_string2).unwrap();
226
227 let addr1 = Addr::unchecked("addr1");
229 let addr2 = Addr::unchecked("addr2");
230
231 let map: Map<(SlashingRequestId, &Addr), u64> = Map::new("composite_key_map");
233 let mut storage = MockStorage::new();
234
235 map.save(&mut storage, (id1.clone(), &addr1), &100u64)
237 .unwrap();
238 map.save(&mut storage, (id1.clone(), &addr2), &200u64)
239 .unwrap();
240 map.save(&mut storage, (id2.clone(), &addr1), &300u64)
241 .unwrap();
242 map.save(&mut storage, (id2.clone(), &addr2), &400u64)
243 .unwrap();
244
245 let value1 = map.load(&storage, (id1.clone(), &addr1)).unwrap();
247 let value2 = map.load(&storage, (id1.clone(), &addr2)).unwrap();
248 let value3 = map.load(&storage, (id2.clone(), &addr1)).unwrap();
249 let value4 = map.load(&storage, (id2.clone(), &addr2)).unwrap();
250
251 assert_eq!(value1, 100u64);
253 assert_eq!(value2, 200u64);
254 assert_eq!(value3, 300u64);
255 assert_eq!(value4, 400u64);
256
257 let id1_entries: Vec<_> = map
259 .prefix(id1)
260 .range(&storage, None, None, cosmwasm_std::Order::Ascending)
261 .collect::<StdResult<Vec<_>>>()
262 .unwrap();
263
264 assert_eq!(id1_entries.len(), 2);
266 assert_eq!(id1_entries[0], (addr1.clone(), 100u64));
267 assert_eq!(id1_entries[1], (addr2.clone(), 200u64));
268
269 let id2_entries: Vec<_> = map
271 .prefix(id2)
272 .range(&storage, None, None, cosmwasm_std::Order::Ascending)
273 .collect::<StdResult<Vec<_>>>()
274 .unwrap();
275
276 assert_eq!(id2_entries.len(), 2);
278 assert_eq!(id2_entries[0], (addr1, 300u64));
279 assert_eq!(id2_entries[1], (addr2, 400u64));
280 }
281 }
282}