aleo_struct_parser/
serde.rs

1use serde::de::{MapAccess, SeqAccess};
2use serde_json::Value;
3
4use crate::number::{try_parse_integer, try_parse_unsigned_integer};
5
6struct AleoDeserializer {
7    ast: Value,
8}
9
10impl AleoDeserializer {
11    fn new(input: &str) -> Self {
12        let ast = crate::parse_struct(input);
13        Self { ast: ast }
14    }
15
16    fn from_value(value: Value) -> Self {
17        Self { ast: value }
18    }
19}
20
21macro_rules! impl_deserialize_any {
22    ($($method:ident),*) => {
23        $(
24            fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
25            where
26                V: serde::de::Visitor<'de>,
27            {
28                self.deserialize_any(visitor)
29            }
30        )*
31    };
32}
33
34impl<'de> serde::Deserializer<'de> for AleoDeserializer {
35    type Error = serde_json::Error;
36
37    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
38    where
39        V: serde::de::Visitor<'de>,
40    {
41        match self.ast {
42            serde_json::Value::Null => visitor.visit_none(),
43            serde_json::Value::Bool(v) => visitor.visit_bool(v),
44            serde_json::Value::Number(number) => visitor.visit_i64(number.as_i64().unwrap()),
45            serde_json::Value::String(str) => {
46                if let Some((number, bitsize)) = try_parse_unsigned_integer(&str) {
47                    match bitsize {
48                        8 => visitor.visit_u8(number as u8),
49                        16 => visitor.visit_u16(number as u16),
50                        32 => visitor.visit_u32(number as u32),
51                        64 => visitor.visit_u64(number as u64),
52                        _ => visitor.visit_u128(number),
53                    }
54                } else if let Some((number, bitsize)) = try_parse_integer(&str) {
55                    match bitsize {
56                        8 => visitor.visit_i8(number as i8),
57                        16 => visitor.visit_i16(number as i16),
58                        32 => visitor.visit_i32(number as i32),
59                        64 => visitor.visit_i64(number as i64),
60                        _ => visitor.visit_i128(number),
61                    }
62                } else {
63                    visitor.visit_str(&str)
64                }
65            }
66            serde_json::Value::Array(values) => {
67                struct JsonSeqAccess {
68                    iter: Vec<Value>,
69                    idx: usize,
70                }
71                impl<'de> SeqAccess<'de> for JsonSeqAccess {
72                    type Error = serde_json::Error;
73                    fn next_element_seed<T>(
74                        &mut self,
75                        seed: T,
76                    ) -> Result<Option<T::Value>, Self::Error>
77                    where
78                        T: serde::de::DeserializeSeed<'de>,
79                    {
80                        if self.idx >= self.iter.len() {
81                            return Ok(None);
82                        }
83                        let res = self
84                            .iter
85                            .get(self.idx)
86                            .map(|v| seed.deserialize(AleoDeserializer::from_value(v.clone())))
87                            .transpose();
88                        self.idx += 1;
89                        res
90                    }
91                }
92                visitor.visit_seq(JsonSeqAccess {
93                    iter: values,
94                    idx: 0,
95                })
96            }
97            serde_json::Value::Object(map) => {
98                struct JsonMapAccess {
99                    iter: std::vec::IntoIter<(String, Value)>,
100                    value: Option<Value>,
101                }
102                impl<'de> MapAccess<'de> for JsonMapAccess {
103                    type Error = serde_json::Error;
104                    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error>
105                    where
106                        K: serde::de::DeserializeSeed<'de>,
107                    {
108                        if let Some((k, v)) = self.iter.next() {
109                            self.value = Some(v);
110                            seed.deserialize(Value::String(k)).map(Some)
111                        } else {
112                            Ok(None)
113                        }
114                    }
115                    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
116                    where
117                        V: serde::de::DeserializeSeed<'de>,
118                    {
119                        let v = self
120                            .value
121                            .take()
122                            .expect("value must be available after key");
123                        let de = AleoDeserializer::from_value(v);
124                        seed.deserialize(de)
125                    }
126                }
127                let entries: Vec<(String, Value)> = map.into_iter().collect();
128                visitor.visit_map(JsonMapAccess {
129                    iter: entries.into_iter(),
130                    value: None,
131                })
132            }
133        }
134    }
135
136    impl_deserialize_any! {
137        deserialize_bool,
138        deserialize_i8,
139        deserialize_i16,
140        deserialize_i32,
141        deserialize_i64,
142        deserialize_i128,
143        deserialize_u8,
144        deserialize_u16,
145        deserialize_u32,
146        deserialize_u64,
147        deserialize_u128,
148        deserialize_f32,
149        deserialize_f64,
150        deserialize_char,
151        deserialize_str,
152        deserialize_string,
153        deserialize_bytes,
154        deserialize_byte_buf,
155        deserialize_option,
156        deserialize_unit,
157        deserialize_seq,
158        deserialize_map,
159        deserialize_identifier,
160        deserialize_ignored_any
161    }
162
163    fn deserialize_unit_struct<V>(
164        self,
165        _name: &'static str,
166        visitor: V,
167    ) -> Result<V::Value, Self::Error>
168    where
169        V: serde::de::Visitor<'de>,
170    {
171        self.deserialize_any(visitor)
172    }
173
174    fn deserialize_newtype_struct<V>(
175        self,
176        _name: &'static str,
177        visitor: V,
178    ) -> Result<V::Value, Self::Error>
179    where
180        V: serde::de::Visitor<'de>,
181    {
182        self.deserialize_any(visitor)
183    }
184
185    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
186    where
187        V: serde::de::Visitor<'de>,
188    {
189        self.deserialize_any(visitor)
190    }
191
192    fn deserialize_tuple_struct<V>(
193        self,
194        _name: &'static str,
195        _len: usize,
196        visitor: V,
197    ) -> Result<V::Value, Self::Error>
198    where
199        V: serde::de::Visitor<'de>,
200    {
201        self.deserialize_any(visitor)
202    }
203
204    fn deserialize_struct<V>(
205        self,
206        _name: &'static str,
207        _fields: &'static [&'static str],
208        visitor: V,
209    ) -> Result<V::Value, Self::Error>
210    where
211        V: serde::de::Visitor<'de>,
212    {
213        self.deserialize_any(visitor)
214    }
215
216    fn deserialize_enum<V>(
217        self,
218        _name: &'static str,
219        _variants: &'static [&'static str],
220        visitor: V,
221    ) -> Result<V::Value, Self::Error>
222    where
223        V: serde::de::Visitor<'de>,
224    {
225        self.deserialize_any(visitor)
226    }
227}
228
229pub fn from_str<'a, T>(s: &'a str) -> Result<T, serde_json::Error>
230where
231    T: serde::Deserialize<'a>,
232{
233    let de = AleoDeserializer::new(s);
234    T::deserialize(de)
235}
236
237#[derive(Debug)]
238pub struct Address {
239    pub address: String,
240}
241
242impl<'de> serde::Deserialize<'de> for Address {
243    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
244    where
245        D: serde::Deserializer<'de>,
246    {
247        let value = String::deserialize(deserializer)?;
248        Ok(Address { address: value })
249    }
250}
251
252#[cfg(test)]
253mod tests {
254    use serde::Deserialize;
255
256    use super::*;
257
258    #[test]
259    fn test_parse_struct() {
260        #[derive(Debug, Deserialize)]
261        #[allow(dead_code)]
262        struct TestStruct {
263            program_id: String,
264            function_name: String,
265            arguments: Vec<Address>,
266            struct2: TestStruct2,
267            vec3: Vec<TestStruct2>,
268        }
269
270        #[derive(Debug, Deserialize)]
271        #[allow(dead_code)]
272        struct TestStruct2 {
273            program_id: String,
274            function_name: String,
275            arguments: (Address, u64),
276        }
277
278        let input = r#"
279            {
280                program_id: puzzle_arcade_ticket_v002.aleo,
281                function_name: mint,
282                arguments: [
283                    aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl
284                ],
285                struct2: {
286                    program_id: puzzle_arcade_ticket_v002.aleo,
287                    function_name: mint,
288                    arguments: [
289                        aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl,
290                        1000u64
291                    ]
292                },
293                vec3: [
294                    {
295                        program_id: puzzle_arcade_ticket_v002.aleo,
296                        function_name: mint,
297                        arguments: [
298                            aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl,
299                            1000u64
300                        ]
301                    }
302                ],
303                extra: extra
304            }
305        "#;
306
307        let result: TestStruct = from_str(input).unwrap();
308        assert_eq!(result.program_id, "puzzle_arcade_ticket_v002.aleo");
309        assert_eq!(result.struct2.arguments.1, 1000);
310
311        let input = r#"
312            [
313                aleo13dn2lyphtrn8mujxcqt4vm2rc567k0s3gnnks985p0hhyvfc9yqqy6rdsl,
314                1000u64
315            ]
316            "#;
317
318        let result: (Address, u64) = from_str(input).unwrap();
319
320        assert_eq!(result.1, 1000);
321
322        let num: u64 = from_str("100u64").unwrap();
323        assert_eq!(num, 100);
324    }
325}