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::{
190 format,
191 string::{String, ToString},
192 };
193 use core::{fmt, marker::PhantomData, str::FromStr};
194 use serde::de::Error;
195
196 struct AnyVisitor<T>(PhantomData<T>);
198
199 impl<'de, T: FromStr> serde::de::Visitor<'de> for AnyVisitor<T> {
200 type Value = T;
201
202 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
203 formatter.write_str("string or integer")
204 }
205
206 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
207 where
208 E: Error,
209 {
210 let inner: T = v
211 .parse()
212 .map_err(|_| serde::de::Error::custom("failure to parse string data"))?;
213 Ok(inner)
214 }
215
216 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
217 where
218 E: Error,
219 {
220 let inner: T = v
221 .parse()
222 .map_err(|_| serde::de::Error::custom("failure to parse string data"))?;
223 Ok(inner)
224 }
225
226 fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
227 where
228 E: Error,
229 {
230 let inner: T = v
231 .to_string()
232 .parse()
233 .map_err(|_| serde::de::Error::custom("failure to parse string data"))?;
234 Ok(inner)
235 }
236 }
237
238 pub fn serialize<S, T: fmt::Display>(data: T, serializer: S) -> Result<S::Ok, S::Error>
240 where
241 S: serde::Serializer,
242 {
243 let output = format!("{data}");
244 serializer.collect_str(&output)
245 }
246
247 pub fn deserialize<'de, D, T: FromStr>(deserializer: D) -> Result<T, D::Error>
249 where
250 D: serde::Deserializer<'de>,
251 {
252 let data = deserializer.deserialize_any(AnyVisitor(PhantomData::<T>))?;
253 T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse string"))
254 }
255}
256
257pub mod seq_of_str {
259 use super::*;
260 use core::{fmt, marker::PhantomData, str::FromStr};
261 use serde::{
262 de::{Deserializer, Error},
263 ser::SerializeSeq,
264 };
265
266 pub fn serialize<S, T, U>(data: T, serializer: S) -> Result<S::Ok, S::Error>
268 where
269 S: serde::Serializer,
270 T: AsRef<[U]>,
271 U: fmt::Display,
272 {
273 let mut seq = serializer.serialize_seq(None)?;
274 for elem in data.as_ref().iter() {
275 let rendered_elem = format!("{elem}");
276 seq.serialize_element(&rendered_elem)?;
277 }
278 seq.end()
279 }
280
281 struct Visitor<T>(PhantomData<Vec<T>>);
283
284 impl<'de, T: FromStr> serde::de::Visitor<'de> for Visitor<T> {
285 type Value = Vec<T>;
286
287 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
288 formatter.write_str("sequence of string")
289 }
290
291 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
292 where
293 S: serde::de::SeqAccess<'de>,
294 {
295 let mut coll = Vec::with_capacity(access.size_hint().unwrap_or(0));
296
297 while let Some(elem) = access.next_element()? {
298 let recovered_elem = T::from_str(elem).map_err(|_| {
299 Error::custom("failure to parse element of sequence from string")
300 })?;
301 coll.push(recovered_elem);
302 }
303 Ok(coll)
304 }
305 }
306
307 pub fn deserialize<'de, D, T, U>(deserializer: D) -> Result<T, D::Error>
309 where
310 D: Deserializer<'de>,
311 T: TryFrom<Vec<U>>,
312 U: FromStr,
313 {
314 let data = deserializer.deserialize_seq(Visitor(PhantomData))?;
315 T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse collection"))
316 }
317}
318
319pub mod seq_of_u8_str_or_hex {
322 use super::*;
323 use alloc::string::String;
324 use core::{fmt, marker::PhantomData, str::FromStr};
325 use serde::de::{Deserializer, Error};
326
327 pub use seq_of_str::serialize;
328
329 struct AnyVisitor(PhantomData<Vec<u8>>);
331
332 impl<'de> serde::de::Visitor<'de> for AnyVisitor {
333 type Value = Vec<u8>;
334
335 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
336 formatter.write_str("sequence of string or hex string")
337 }
338
339 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
340 where
341 E: Error,
342 {
343 let data = try_bytes_from_hex_str(v).map_err(serde::de::Error::custom)?;
344 Ok(data)
345 }
346
347 fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
348 where
349 E: Error,
350 {
351 let data = try_bytes_from_hex_str(&v).map_err(serde::de::Error::custom)?;
352 Ok(data)
353 }
354
355 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
356 where
357 S: serde::de::SeqAccess<'de>,
358 {
359 let mut coll = Vec::with_capacity(access.size_hint().unwrap_or(0));
360
361 while let Some(elem) = access.next_element()? {
362 let recovered_elem = <u8>::from_str(elem).map_err(|_| {
363 Error::custom("failure to parse element of sequence from string")
364 })?;
365 coll.push(recovered_elem);
366 }
367 Ok(coll)
368 }
369 }
370
371 pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
373 where
374 D: Deserializer<'de>,
375 T: TryFrom<Vec<u8>>,
376 {
377 let data = deserializer.deserialize_any(AnyVisitor(PhantomData))?;
378 T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse collection"))
379 }
380}
381
382#[cfg(test)]
383mod test {
384 use super::{as_string, seq_of_u8_str_or_hex};
385 use ismp::router::{GetRequest, GetResponse, PostRequest, StorageValue};
386 use primitive_types::{H256, H512};
387 use serde::Deserialize;
388
389 #[test]
390 fn should_deserialize_from_hex_string_and_sequence_of_strings() {
391 #[derive(Deserialize, Debug, PartialEq, Eq)]
392 struct TestData {
393 #[serde(with = "seq_of_u8_str_or_hex")]
394 data: Vec<u8>,
395 #[serde(with = "as_string")]
396 value: u64,
397 }
398
399 let json_value_1 = r#"{
400 "data":"0x00050708",
401 "value":29716
402 }"#;
403 let json_value_2 = r#"{
404 "data":["0", "5", "7", "8"],
405 "value": "29716"
406 }"#;
407
408 let deserialized_1 = serde_json::from_str::<TestData>(json_value_1);
409 let deserialized_2 = serde_json::from_str::<TestData>(json_value_2);
410 println!("{deserialized_1:?}");
411 println!("{deserialized_2:?}");
412
413 assert!(deserialized_1.is_ok());
414 assert!(deserialized_2.is_ok());
415
416 assert!(deserialized_1.unwrap() == deserialized_2.unwrap());
417 }
418
419 #[test]
420 fn serialize_and_deserialize_post_request() {
421 let post = PostRequest {
422 source: ismp::host::StateMachine::Polkadot(100),
423 dest: ismp::host::StateMachine::Polkadot(2000),
424 nonce: 300,
425 from: H256::random().0.to_vec(),
426 to: H256::random().0.to_vec(),
427 timeout_timestamp: 0,
428 body: H512::random().0.to_vec(),
429 };
430
431 let serialized = serde_json::to_string(&post).unwrap();
432
433 println!("{serialized:?}\n");
434
435 let deserialized: PostRequest = serde_json::from_str(&serialized).unwrap();
436
437 assert_eq!(post, deserialized);
438 }
439
440 #[test]
441 fn serialize_and_deserialize_get_request() {
442 let get = GetRequest {
443 source: ismp::host::StateMachine::Polkadot(100),
444 dest: ismp::host::StateMachine::Polkadot(2000),
445 nonce: 300,
446 context: Default::default(),
447 from: H256::random().0.to_vec(),
448 keys: vec![
449 H256::random().0.to_vec(),
450 H256::random().0.to_vec(),
451 H256::random().0.to_vec(),
452 ],
453 timeout_timestamp: 40000,
454 height: 289900,
455 };
456
457 let serialized = serde_json::to_string(&get).unwrap();
458
459 println!("{serialized:?}\n");
460
461 let deserialized: GetRequest = serde_json::from_str(&serialized).unwrap();
462
463 assert_eq!(get, deserialized);
464 }
465
466 #[test]
467 fn serialize_and_deserialize_get_response() {
468 let get = GetRequest {
469 source: ismp::host::StateMachine::Polkadot(100),
470 dest: ismp::host::StateMachine::Polkadot(2000),
471 nonce: 300,
472 context: Default::default(),
473
474 from: H256::random().0.to_vec(),
475 keys: vec![
476 H256::random().0.to_vec(),
477 H256::random().0.to_vec(),
478 H256::random().0.to_vec(),
479 ],
480 timeout_timestamp: 40000,
481 height: 289900,
482 };
483
484 let response = GetResponse {
485 get,
486 values: vec![
487 StorageValue {
488 key: H256::random().0.to_vec(),
489 value: Some(H256::random().0.to_vec()),
490 },
491 StorageValue { key: H256::random().0.to_vec(), value: None },
492 StorageValue {
493 key: H256::random().0.to_vec(),
494 value: Some(H256::random().0.to_vec()),
495 },
496 ],
497 };
498
499 let serialized = serde_json::to_string(&response).unwrap();
500
501 println!("{serialized:?}\n");
502
503 let deserialized: GetResponse = serde_json::from_str(&serialized).unwrap();
504
505 assert_eq!(response, deserialized);
506 }
507
508 #[test]
509 fn serialize_state_machine_id() {
510 use ismp::{consensus::StateMachineId, host::StateMachine};
511 let state_machine_updated =
512 StateMachineId { state_id: StateMachine::Evm(11155111), consensus_state_id: *b"ETH0" };
513 let serialized = serde_json::to_string(&state_machine_updated).unwrap();
514
515 println!("{serialized:?}\n");
516
517 let deserialized: StateMachineId = serde_json::from_str(&serialized).unwrap();
518
519 assert_eq!(state_machine_updated, deserialized);
520 }
521}