Skip to content

Commit 99d09a8

Browse files
committed
support deserializing string from integers
1 parent 43d8a9b commit 99d09a8

File tree

1 file changed

+57
-11
lines changed

1 file changed

+57
-11
lines changed

modules/utils/serde/src/lib.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,54 @@ pub mod seq_of_hex {
186186

187187
/// String serializer and deserializer
188188
pub mod as_string {
189-
use alloc::{format, string::String};
190-
use core::{fmt, str::FromStr};
191-
use serde::de::Deserialize;
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+
/// Serde Visitor for deserializing sequence of strings or hex string into sequence of bytes
197+
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+
}
192237

193238
/// Serialize into a string
194239
pub fn serialize<S, T: fmt::Display>(data: T, serializer: S) -> Result<S::Ok, S::Error>
@@ -204,11 +249,8 @@ pub mod as_string {
204249
where
205250
D: serde::Deserializer<'de>,
206251
{
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)
252+
let data = deserializer.deserialize_any(AnyVisitor(PhantomData::<T>))?;
253+
T::try_from(data).map_err(|_| serde::de::Error::custom("failure to parse string"))
212254
}
213255
}
214256

@@ -339,7 +381,7 @@ pub mod seq_of_u8_str_or_hex {
339381

340382
#[cfg(test)]
341383
mod test {
342-
use super::seq_of_u8_str_or_hex;
384+
use super::{as_string, seq_of_u8_str_or_hex};
343385
use ismp::router::{GetRequest, GetResponse, PostRequest, PostResponse, StorageValue};
344386
use primitive_types::{H256, H512};
345387
use serde::Deserialize;
@@ -350,13 +392,17 @@ mod test {
350392
struct TestData {
351393
#[serde(with = "seq_of_u8_str_or_hex")]
352394
data: Vec<u8>,
395+
#[serde(with = "as_string")]
396+
value: u64,
353397
}
354398

355399
let json_value_1 = r#"{
356-
"data":"0x00050708"
400+
"data":"0x00050708",
401+
"value":29716
357402
}"#;
358403
let json_value_2 = r#"{
359-
"data":["0", "5", "7", "8"]
404+
"data":["0", "5", "7", "8"],
405+
"value": "29716"
360406
}"#;
361407

362408
let deserialized_1 = serde_json::from_str::<TestData>(json_value_1);

0 commit comments

Comments
 (0)