xrpl/_serde/
mod.rs

1//! Serde functionalities
2
3use crate::models::FlagCollection;
4use alloc::format;
5use alloc::vec::Vec;
6use core::hash::BuildHasherDefault;
7use core::{convert::TryFrom, fmt::Debug};
8use fnv::FnvHasher;
9use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
10use serde_json::Value;
11use strum::IntoEnumIterator;
12
13pub type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FnvHasher>>;
14
15fn serialize_flag<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
16where
17    F: Serialize + IntoEnumIterator,
18    S: Serializer,
19{
20    let flags_value_result: Result<Value, serde_json::Error> = serde_json::to_value(flags);
21    match flags_value_result {
22        Ok(flags_as_value) => {
23            let flag_vec_result: Result<Vec<u32>, serde_json::Error> =
24                serde_json::from_value(flags_as_value);
25            match flag_vec_result {
26                Ok(flags_vec) => s.serialize_u32(flags_vec.iter().sum()),
27                Err(_) => {
28                    // TODO: Find a way to use custom errors
29                    Err(ser::Error::custom("SerdeIntermediateStepError: Failed to turn flags into `Vec<u32>` during serialization"))
30                }
31            }
32        }
33        Err(_) => Err(ser::Error::custom(
34            "SerdeIntermediateStepError: Failed to turn flags into `Value` during serialization",
35        )),
36    }
37}
38
39fn deserialize_flags<'de, D, F>(d: D) -> Result<FlagCollection<F>, D::Error>
40where
41    F: Serialize + IntoEnumIterator + Debug,
42    D: Deserializer<'de>,
43{
44    let flags_u32 = u32::deserialize(d)?;
45    FlagCollection::<F>::try_from(flags_u32).map_err(|_e| {
46        de::Error::custom(format!(
47            "SerdeIntermediateStepError: Failed to turn `u32` into `FlagCollection<{}>` during deserialization",
48            core::any::type_name::<F>()
49        ))
50    })
51}
52
53/// A `mod` to be used on transaction `flags` fields. It serializes the `Vec<Flag>` into a `u32`,
54/// representing the bit-flags, and deserializes the `u32` back into `Vec<Flag>` for internal uses.
55pub(crate) mod txn_flags {
56    use core::fmt::Debug;
57
58    use crate::_serde::{deserialize_flags, serialize_flag};
59
60    use serde::{Deserializer, Serialize, Serializer};
61
62    use crate::models::FlagCollection;
63    use strum::IntoEnumIterator;
64
65    pub fn serialize<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
66    where
67        F: Serialize + IntoEnumIterator + Debug,
68        S: Serializer,
69    {
70        if flags.0.is_empty() {
71            s.serialize_u32(0)
72        } else {
73            serialize_flag(flags, s)
74        }
75    }
76
77    pub fn deserialize<'de, F, D>(d: D) -> Result<FlagCollection<F>, D::Error>
78    where
79        F: Serialize + IntoEnumIterator + Debug,
80        D: Deserializer<'de>,
81    {
82        let flags_vec_result: Result<FlagCollection<F>, D::Error> = deserialize_flags(d);
83        match flags_vec_result {
84            Ok(flags_vec) => {
85                if flags_vec.0.is_empty() {
86                    Ok(FlagCollection::<F>::default())
87                } else {
88                    Ok(flags_vec)
89                }
90            }
91            Err(error) => Err(error),
92        }
93    }
94}
95
96pub(crate) mod lgr_obj_flags {
97    use core::fmt::Debug;
98
99    use crate::_serde::{deserialize_flags, serialize_flag};
100    use crate::models::FlagCollection;
101    use serde::{Deserializer, Serialize, Serializer};
102    use strum::IntoEnumIterator;
103
104    pub fn serialize<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
105    where
106        F: Serialize + IntoEnumIterator,
107        S: Serializer,
108    {
109        if !flags.0.is_empty() {
110            serialize_flag(flags, s)
111        } else {
112            s.serialize_u32(0)
113        }
114    }
115
116    pub fn deserialize<'de, F, D>(d: D) -> Result<FlagCollection<F>, D::Error>
117    where
118        F: Serialize + IntoEnumIterator + Debug,
119        D: Deserializer<'de>,
120    {
121        deserialize_flags(d)
122    }
123}
124
125/// A macro to tag a struct externally. With `serde` attributes, unfortunately it is not possible to
126/// serialize a struct to json with its name as `key` and its fields as `value`. Example:
127/// `{"Example":{"Field1":"hello","Field2":"world"}}`
128///
129/// Several models need to be serialized in that format. This macro uses a helper to serialize and
130/// deserialize to/from that format.
131///
132/// Resource: https://github.com/serde-rs/serde/issues/554#issuecomment-249211775
133// TODO: Find a way to `#[skip_serializing_none]`
134#[macro_export]
135macro_rules! serde_with_tag {
136    (
137        $(#[$attr:meta])*
138        pub struct $name:ident<$lt:lifetime> {
139            $(
140                $(#[$doc:meta])*
141                pub $field:ident: $ty:ty,
142            )*
143        }
144    ) => {
145        $(#[$attr])*
146        pub struct $name<$lt> {
147            $(
148                $(#[$doc])*
149                pub $field: $ty,
150            )*
151        }
152
153        impl<$lt> ::serde::Serialize for $name<$lt> {
154            fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
155            where
156                S: ::serde::Serializer
157            {
158                #[derive(::serde::Serialize)]
159                #[serde(rename_all = "PascalCase")]
160                #[::serde_with::skip_serializing_none]
161                struct Helper<$lt> {
162                    $(
163                        $field: $ty,
164                    )*
165                }
166
167                let helper = Helper {
168                    $(
169                        $field: self.$field.clone(),
170                    )*
171                };
172
173                let mut state = serializer.serialize_map(Some(1))?;
174                state.serialize_key(stringify!($name))?;
175                state.serialize_value(&helper)?;
176                state.end()
177            }
178        }
179
180        impl<'de: $lt, $lt> ::serde::Deserialize<'de> for $name<$lt> {
181            #[allow(non_snake_case)]
182            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
183            where
184                D: serde::Deserializer<'de>,
185            {
186                #[derive(::serde::Deserialize)]
187                #[serde(rename_all = "PascalCase")]
188                #[::serde_with::skip_serializing_none]
189                struct Helper<$lt> {
190                    $(
191                        $field: $ty,
192                    )*
193                }
194
195                let hash_map: $crate::_serde::HashMap<&$lt str, Helper<$lt>> = $crate::_serde::HashMap::deserialize(deserializer)?;
196                let helper_result = hash_map.get(stringify!($name));
197
198                match helper_result {
199                    Some(helper) => {
200                        Ok(Self {
201                            $(
202                                $field: helper.$field.clone().into(),
203                            )*
204                        })
205                    }
206                    None => {
207                        Err(::serde::de::Error::custom("SerdeIntermediateStepError: Unable to find model name as json key."))
208                    }
209                }
210            }
211        }
212    };
213    (
214        $(#[$attr:meta])*
215        pub struct $name:ident {
216            $(
217                $(#[$doc:meta])*
218                pub $field:ident: $ty:ty,
219            )*
220        }
221    ) => {
222        $(#[$attr])*
223        pub struct $name {
224            $(
225                $(#[$doc])*
226                pub $field: $ty,
227            )*
228        }
229
230        impl ::serde::Serialize for $name {
231            fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
232            where
233                S: ::serde::Serializer
234            {
235                #[derive(::serde::Serialize)]
236                #[serde(rename_all = "PascalCase")]
237                #[::serde_with::skip_serializing_none]
238                struct Helper {
239                    $(
240                        $field: $ty,
241                    )*
242                }
243
244                let helper = Helper {
245                    $(
246                        $field: self.$field.clone(),
247                    )*
248                };
249
250                let mut state = serializer.serialize_map(Some(1))?;
251                state.serialize_key(stringify!($name))?;
252                state.serialize_value(&helper)?;
253                state.end()
254            }
255        }
256
257        impl<'de> ::serde::Deserialize<'de> for $name {
258            #[allow(non_snake_case)]
259            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
260            where
261                D: serde::Deserializer<'de>,
262            {
263                #[derive(::serde::Deserialize)]
264                #[serde(rename_all = "PascalCase")]
265                #[::serde_with::skip_serializing_none]
266                struct Helper {
267                    $(
268                        $field: $ty,
269                    )*
270                }
271
272                let hash_map: $crate::_serde::HashMap<&'de str, Helper> = $crate::_serde::HashMap::deserialize(deserializer)?;
273                let helper_result = hash_map.get(stringify!($name));
274
275                match helper_result {
276                    Some(helper) => {
277                        Ok(Self {
278                            $(
279                                $field: helper.$field.clone().into(),
280                            )*
281                        })
282                    }
283                    None => {
284                        Err(::serde::de::Error::custom("SerdeIntermediateStepError: Unable to find model name as json key."))
285                    }
286                }
287            }
288        }
289    };
290}