1#![cfg_attr(not(feature = "std"), no_std)]
19#![deny(missing_docs)]
20
21extern crate alloc;
22use alloc::{format, vec::Vec};
23use anyhow::anyhow;
24
25const HEX_ENCODING_PREFIX: &str = "0x";
26
27pub fn try_bytes_from_hex_str(s: &str) -> Result<Vec<u8>, anyhow::Error> {
29 let target = s.replace(HEX_ENCODING_PREFIX, "");
30 let data = hex::decode(target).map_err(|e| anyhow!("{e:?}"))?;
31 Ok(data)
32}
33
34pub mod as_hex {
36 use super::*;
37 use alloc::string::String;
38 use serde::de::Deserialize;
39
40 pub fn serialize<S, T: AsRef<[u8]>>(data: T, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: serde::Serializer,
44 {
45 let encoding = hex::encode(data.as_ref());
46 let output = format!("{HEX_ENCODING_PREFIX}{encoding}");
47 serializer.collect_str(&output)
48 }
49
50 pub fn serialize_option<S, T: AsRef<[u8]>>(
52 data: &Option<T>,
53 serializer: S,
54 ) -> Result<S::Ok, S::Error>
55 where
56 S: serde::Serializer,
57 {
58 if let Some(data) = data {
59 let encoding = hex::encode(data.as_ref());
60 let output = format!("{HEX_ENCODING_PREFIX}{encoding}");
61 serializer.collect_str(&output)
62 } else {
63 serializer.collect_str(&"")
64 }
65 }
66
67 pub fn deserialize_option<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
69 where
70 D: serde::Deserializer<'de>,
71 T: TryFrom<Vec<u8>>,
72 {
73 let s = <String>::deserialize(deserializer)?;
74
75 let data = try_bytes_from_hex_str(&s).map_err(serde::de::Error::custom)?;
76 if data.is_empty() {
77 Ok(None)
78 } else {
79 let inner = T::try_from(data).map_err(|_| {
80 serde::de::Error::custom("type failed to parse bytes from hex data")
81 })?;
82 Ok(Some(inner))
83 }
84 }
85
86 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
88 where
89 D: serde::Deserializer<'de>,
90 T: TryFrom<Vec<u8>>,
91 {
92 let s = <String>::deserialize(deserializer)?;
93
94 let data = try_bytes_from_hex_str(&s).map_err(serde::de::Error::custom)?;
95
96 let inner = T::try_from(data)
97 .map_err(|_| serde::de::Error::custom("type failed to parse bytes from hex data"))?;
98 Ok(inner)
99 }
100}
101
102pub mod as_utf8_string {
104 use super::*;
105 use alloc::string::String;
106 use serde::de::Deserialize;
107
108 pub fn serialize<S, T: AsRef<[u8]>>(data: T, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: serde::Serializer,
112 {
113 let output =
114 String::from_utf8(data.as_ref().to_vec()).map_err(serde::ser::Error::custom)?;
115 serializer.collect_str(&output)
116 }
117
118 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
120 where
121 D: serde::Deserializer<'de>,
122 T: From<[u8; 4]>,
123 {
124 let s = <String>::deserialize(deserializer)?;
125
126 let mut bytes = [0u8; 4];
127 bytes.copy_from_slice(s.as_bytes());
128 Ok(bytes.into())
129 }
130}
131
132pub mod seq_of_hex {
134 use super::*;
135 use core::{fmt, marker::PhantomData};
136 use serde::{de::Deserializer, ser::SerializeSeq};
137
138 pub fn serialize<S, T>(data: T, serializer: S) -> Result<S::Ok, S::Error>
140 where
141 S: serde::Serializer,
142 T: AsRef<[Vec<u8>]>,
143 {
144 let mut seq = serializer.serialize_seq(None)?;
145 for elem in data.as_ref().iter() {
146 let encoding = hex::encode(elem);
147 let output = format!("{HEX_ENCODING_PREFIX}{encoding}");
148 seq.serialize_element(&output)?;
149 }
150 seq.end()
151 }
152
153 struct Visitor(PhantomData<Vec<Vec<u8>>>);
154
155 impl<'de> serde::de::Visitor<'de> for Visitor {
156 type Value = Vec<Vec<u8>>;
157
158 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
159 formatter.write_str("sequence of string")
160 }
161
162 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
163 where
164 S: serde::de::SeqAccess<'de>,
165 {
166 let mut coll = Vec::with_capacity(access.size_hint().unwrap_or(0));
167
168 while let Some(elem) = access.next_element()? {
169 let recovered_elem =
170 try_bytes_from_hex_str(elem).map_err(serde::de::Error::custom)?;
171 coll.push(recovered_elem);
172 }
173 Ok(coll)
174 }
175 }
176
177 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<Vec<u8>>, D::Error>
179 where
180 D: Deserializer<'de>,
181 {
182 let data = deserializer.deserialize_seq(Visitor(PhantomData))?;
183 Ok(data)
184 }
185}
186
187pub mod as_string {
189 use alloc::{format, string::String};
190 use core::{fmt, str::FromStr};
191 use serde::de::Deserialize;
192
193 pub fn serialize<S, T: fmt::Display>(data: T, serializer: S) -> Result<S::Ok, S::Error>
195 where
196 S: serde::Serializer,
197 {
198 let output = format!("{data}");
199 serializer.collect_str(&output)
200 }
201
202 pub fn deserialize<'de, D, T: FromStr>(deserializer: D) -> Result<T, D::Error>
204 where
205 D: serde::Deserializer<'de>,
206 {
207 let s: String = <String>::deserialize(deserializer)?;
208 let inner: T = s
209 .parse()
210 .map_err(|_| serde::de::Error::custom("failure to parse string data"))?;
211 Ok(inner)
212 }
213}
214
215pub mod seq_of_str {
217 use super::*;
218 use core::{fmt, marker::PhantomData, str::FromStr};
219 use serde::{
220 de::{Deserializer, Error},
221 ser::SerializeSeq,
222 };
223
224 pub fn serialize<S, T, U>(data: T, serializer: S) -> Result<S::Ok, S::Error>
226 where
227 S: serde::Serializer,
228 T: AsRef<[U]>,
229 U: fmt::Display,
230 {
231 let mut seq = serializer.serialize_seq(None)?;
232 for elem in data.as_ref().iter() {
233 let rendered_elem = format!("{elem}");
234 seq.serialize_element(&rendered_elem)?;
235 }
236 seq.end()
237 }
238
239 struct Visitor<T>(PhantomData<Vec<T>>);
240
241 impl<'de, T: FromStr> serde::de::Visitor<'de> for Visitor<T> {
242 type Value = Vec<T>;
243
244 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
245 formatter.write_str("sequence of string")
246 }
247
248 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
249 where
250 S: serde::de::SeqAccess<'de>,
251 {
252 let mut coll = Vec::with_capacity(access.size_hint().unwrap_or(0));
253
254 while let Some(elem) = access.next_element()? {
255 let recovered_elem = T::from_str(elem).map_err(|_| {
256 Error::custom("failure to parse element of sequence from string")
257 })?;
258 coll.push(recovered_elem);
259 }
260 Ok(coll)
261 }
262 }
263
264 pub fn deserialize<'de, D, T, U>(deserializer: D) -> Result<T, D::Error>
266 where
267 D: Deserializer<'de>,
268 T: TryFrom<Vec<U>>,
269 U: FromStr,
270 {
271 let data = deserializer.deserialize_seq(Visitor(PhantomData))?;
272 T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse collection"))
273 }
274}
275
276#[cfg(test)]
277mod test {
278 use primitive_types::{H256, H512};
279
280 use ismp::router::{GetRequest, GetResponse, PostRequest, PostResponse, StorageValue};
281
282 #[test]
283 fn serialize_and_deserialize_post_request() {
284 let post = PostRequest {
285 source: ismp::host::StateMachine::Polkadot(100),
286 dest: ismp::host::StateMachine::Polkadot(2000),
287 nonce: 300,
288 from: H256::random().0.to_vec(),
289 to: H256::random().0.to_vec(),
290 timeout_timestamp: 0,
291 body: H512::random().0.to_vec(),
292 };
293
294 let serialized = serde_json::to_string(&post).unwrap();
295
296 println!("{serialized:?}\n");
297
298 let deserialized: PostRequest = serde_json::from_str(&serialized).unwrap();
299
300 assert_eq!(post, deserialized);
301 }
302
303 #[test]
304 fn serialize_and_deserialize_post_response() {
305 let post = PostRequest {
306 source: ismp::host::StateMachine::Polkadot(100),
307 dest: ismp::host::StateMachine::Polkadot(2000),
308 nonce: 300,
309 from: H256::random().0.to_vec(),
310 to: H256::random().0.to_vec(),
311 timeout_timestamp: 0,
312 body: H512::random().0.to_vec(),
313 };
314
315 let response =
316 PostResponse { post, response: H512::random().0.to_vec(), timeout_timestamp: 30000 };
317
318 let serialized = serde_json::to_string(&response).unwrap();
319
320 println!("{serialized:?}\n");
321
322 let deserialized: PostResponse = serde_json::from_str(&serialized).unwrap();
323
324 assert_eq!(response, deserialized);
325 }
326
327 #[test]
328 fn serialize_and_deserialize_get_request() {
329 let get = GetRequest {
330 source: ismp::host::StateMachine::Polkadot(100),
331 dest: ismp::host::StateMachine::Polkadot(2000),
332 nonce: 300,
333 context: Default::default(),
334 from: H256::random().0.to_vec(),
335 keys: vec![
336 H256::random().0.to_vec(),
337 H256::random().0.to_vec(),
338 H256::random().0.to_vec(),
339 ],
340 timeout_timestamp: 40000,
341 height: 289900,
342 };
343
344 let serialized = serde_json::to_string(&get).unwrap();
345
346 println!("{serialized:?}\n");
347
348 let deserialized: GetRequest = serde_json::from_str(&serialized).unwrap();
349
350 assert_eq!(get, deserialized);
351 }
352
353 #[test]
354 fn serialize_and_deserialize_get_response() {
355 let get = GetRequest {
356 source: ismp::host::StateMachine::Polkadot(100),
357 dest: ismp::host::StateMachine::Polkadot(2000),
358 nonce: 300,
359 context: Default::default(),
360
361 from: H256::random().0.to_vec(),
362 keys: vec![
363 H256::random().0.to_vec(),
364 H256::random().0.to_vec(),
365 H256::random().0.to_vec(),
366 ],
367 timeout_timestamp: 40000,
368 height: 289900,
369 };
370
371 let response = GetResponse {
372 get,
373 values: vec![
374 StorageValue {
375 key: H256::random().0.to_vec(),
376 value: Some(H256::random().0.to_vec()),
377 },
378 StorageValue { key: H256::random().0.to_vec(), value: None },
379 StorageValue {
380 key: H256::random().0.to_vec(),
381 value: Some(H256::random().0.to_vec()),
382 },
383 ],
384 };
385
386 let serialized = serde_json::to_string(&response).unwrap();
387
388 println!("{serialized:?}\n");
389
390 let deserialized: GetResponse = serde_json::from_str(&serialized).unwrap();
391
392 assert_eq!(response, deserialized);
393 }
394
395 #[test]
396 fn serialize_state_machine_id() {
397 use ismp::{consensus::StateMachineId, host::StateMachine};
398 let state_machine_updated =
399 StateMachineId { state_id: StateMachine::Evm(11155111), consensus_state_id: *b"ETH0" };
400 let serialized = serde_json::to_string(&state_machine_updated).unwrap();
401
402 println!("{serialized:?}\n");
403
404 let deserialized: StateMachineId = serde_json::from_str(&serialized).unwrap();
405
406 assert_eq!(state_machine_updated, deserialized);
407 }
408}