facet_json_read/
deserialize.rs

1use std::num::NonZero;
2
3use crate::parser::{JsonParseErrorKind, JsonParseErrorWithContext, JsonParser};
4
5use facet_core::{Facet, Opaque, OpaqueUninit};
6use facet_poke::{PokeUninit, PokeValueUninit};
7use log::trace;
8
9/// Deserializes a JSON string into a value of type `T` that implements `Facet`.
10///
11/// This function takes a JSON string representation and converts it into a Rust
12/// value of the specified type `T`. The type must implement the `Facet` trait
13/// to provide the necessary type information for deserialization.
14///
15/// # Parameters
16/// * `json` - A string slice containing the JSON to deserialize
17///
18/// # Returns
19/// * `Ok(T)` - The successfully deserialized value
20/// * `Err(JsonParseErrorWithContext)` - An error with context if deserialization fails
21///
22/// # Example
23/// ```
24/// # use facet_core::Facet;
25/// # use facet_derive::Facet;
26/// # use facet_core as facet;
27/// # #[derive(Facet)]
28/// # struct Person { name: String, age: u64 }
29/// let json = r#"{"name":"Alice","age":30}"#;
30/// let person: Person = facet_json_read::from_str(json).unwrap();
31/// ```
32pub fn from_str<T: Facet>(json: &str) -> Result<T, JsonParseErrorWithContext<'_>> {
33    let (poke, _guard) = PokeUninit::alloc::<T>();
34    let opaque = from_str_opaque(poke, json)?;
35    Ok(unsafe { opaque.read::<T>() })
36}
37
38/// Deserialize a `Poke` object from a JSON string.
39pub fn from_str_opaque<'input, 'mem>(
40    poke: PokeUninit<'mem>,
41    json: &'input str,
42) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>> {
43    trace!("Starting JSON deserialization");
44    let mut parser = JsonParser::new(json);
45    deserialize_value(&mut parser, poke)
46}
47
48macro_rules! int {
49    ($parser:expr, $parsed:expr, $pv:expr, $type:ty) => {
50        if $pv.shape().is_type::<$type>() {
51            let n = <$type>::try_from($parsed?).map_err(|e| {
52                $parser.make_error(JsonParseErrorKind::Custom(format!(
53                    "Invalid value for {}: {e}",
54                    stringify!($type)
55                )))
56            })?;
57            return Ok($pv.put(n));
58        }
59
60        if $pv.shape().is_type::<NonZero<$type>>() {
61            let n = <$type>::try_from($parsed?).map_err(|e| {
62                $parser.make_error(JsonParseErrorKind::Custom(format!(
63                    "Invalid value for core::num::NonZero<{}>: {e}",
64                    stringify!($type)
65                )))
66            })?;
67            let n = NonZero::new(n).ok_or_else(|| {
68                $parser.make_error(JsonParseErrorKind::Custom(format!(
69                    "Can't deserialize zero to core::num::NonZero<{}>",
70                    stringify!($type)
71                )))
72            })?;
73
74            return Ok($pv.put(n));
75        }
76    };
77}
78
79macro_rules! unsigneds {
80    ($parser:expr, $pv:expr, $type:ty, $($types:ty),*) => {
81        int!($parser, $parser.parse_u64(), $pv, $type);
82        unsigneds!($parser, $pv, $($types),*);
83    };
84    ($parser:expr, $pv:expr, $type:ty) => {
85        int!($parser, $parser.parse_u64(), $pv, $type);
86    };
87}
88
89macro_rules! signeds {
90    ($parser:expr, $pv:expr, $type:ty, $($types:ty),*) => {
91        int!($parser, $parser.parse_i64(), $pv, $type);
92        signeds!($parser, $pv, $($types),*);
93    };
94    ($parser:expr, $pv:expr, $type:ty) => {
95        int!($parser, $parser.parse_i64(), $pv, $type);
96    };
97}
98
99/// Deserializes a value from JSON using an iterative approach.
100///
101/// This function takes a JSON parser and a Poke object and deserializes the JSON
102/// into the Poke object. It uses an iterative approach with a stack to avoid
103/// recursion.
104fn deserialize_value<'input, 'mem>(
105    parser: &mut JsonParser<'input>,
106    root_poke: PokeUninit<'mem>,
107) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>> {
108    use std::collections::VecDeque;
109
110    enum StackItem<'mem> {
111        Value {
112            poke: PokeUninit<'mem>,
113        },
114        FinishStruct {
115            ps: facet_poke::PokeStruct<'mem>,
116        },
117        StructField {
118            key: String,
119        },
120        AfterStructField {
121            index: usize,
122        },
123        FinishList {
124            pl: facet_poke::PokeList<'mem>,
125        },
126        AfterListItem {
127            item: OpaqueUninit<'mem>,
128        },
129        FinishMap {
130            pm: facet_poke::PokeMap<'mem>,
131        },
132        AfterMapValue {
133            key: String,
134            value: OpaqueUninit<'mem>,
135        },
136    }
137
138    let mut result = None;
139    let mut stack = VecDeque::new();
140    stack.push_back(StackItem::Value { poke: root_poke });
141
142    while let Some(item) = stack.pop_front() {
143        match item {
144            StackItem::Value { poke } => {
145                let shape = poke.shape();
146                trace!("Deserializing {shape}");
147
148                match poke {
149                    PokeUninit::Scalar(pv) => {
150                        trace!("Deserializing \x1b[1;36mscalar\x1b[0m");
151                        fn aux<'input, 'mem>(
152                            parser: &mut JsonParser<'input>,
153                            pv: PokeValueUninit<'mem>,
154                        ) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>>
155                        {
156                            if pv.shape().is_type::<String>() {
157                                let s = parser.parse_string()?;
158                                let data = pv.put(s);
159                                return Ok(data);
160                            }
161                            if pv.shape().is_type::<bool>() {
162                                let b = parser.parse_bool()?;
163                                return Ok(pv.put(b));
164                            }
165                            if pv.shape().is_type::<f32>() {
166                                let n = parser.parse_f64()? as f32;
167                                return Ok(pv.put(n));
168                            }
169                            if pv.shape().is_type::<f64>() {
170                                let n = parser.parse_f64()?;
171                                return Ok(pv.put(n));
172                            }
173
174                            unsigneds!(parser, pv, u8, u16, u32, u64, u128, usize);
175                            signeds!(parser, pv, i8, i16, i32, i64, i128, isize);
176
177                            panic!("Unknown scalar shape: {}", pv.shape());
178                        }
179
180                        result = Some(aux(parser, pv)?);
181                    }
182                    PokeUninit::Struct(ps) => {
183                        trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
184                        stack.push_front(StackItem::FinishStruct { ps });
185
186                        let first_key = parser.expect_object_start()?;
187                        if let Some(key) = first_key {
188                            stack.push_front(StackItem::StructField { key });
189                        }
190                    }
191                    PokeUninit::List(list_uninit) => {
192                        trace!("Deserializing \x1b[1;36marray\x1b[0m");
193                        parser.expect_array_start()?;
194
195                        let pl = list_uninit.init(None).unwrap_or_else(|_| {
196                            panic!("Failed to initialize list");
197                        });
198
199                        let has_element = parser.parse_array_element()?;
200
201                        if let Some(true) = has_element {
202                            let item_shape = pl.def().t;
203                            let item_data =
204                                OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
205                            let item_poke =
206                                unsafe { PokeUninit::unchecked_new(item_data, item_shape) };
207
208                            stack.push_front(StackItem::FinishList { pl });
209                            stack.push_front(StackItem::AfterListItem { item: item_data });
210                            stack.push_front(StackItem::Value { poke: item_poke });
211                        } else {
212                            stack.push_front(StackItem::FinishList { pl });
213                        }
214                    }
215                    PokeUninit::Map(map_uninit) => {
216                        trace!("Deserializing \x1b[1;36mhashmap\x1b[0m");
217                        let first_key = parser.expect_object_start()?;
218
219                        let pm = map_uninit.init(None).unwrap_or_else(|_| {
220                            panic!("Failed to initialize map"); // TODO: map errors
221                        });
222
223                        if let Some(key) = first_key {
224                            let value_shape = pm.def().v;
225                            let value_data =
226                                OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
227                            let value_poke =
228                                unsafe { PokeUninit::unchecked_new(value_data, value_shape) };
229
230                            stack.push_front(StackItem::FinishMap { pm });
231                            stack.push_front(StackItem::AfterMapValue {
232                                key,
233                                value: value_data,
234                            });
235                            stack.push_front(StackItem::Value { poke: value_poke });
236                        } else {
237                            stack.push_front(StackItem::FinishMap { pm });
238                        }
239                    }
240                    PokeUninit::Enum(pe) => {
241                        trace!("Deserializing \x1b[1;36menum\x1b[0m");
242                        let variant_str = parser.parse_string()?;
243
244                        let pe = pe.set_variant_by_name(&variant_str).map_err(|_| {
245                            parser.make_error(JsonParseErrorKind::Custom(format!(
246                                "Invalid enum variant: {}",
247                                variant_str
248                            )))
249                        })?;
250
251                        trace!("Finished deserializing \x1b[1;36menum\x1b[0m");
252                        let opaque = pe.build_in_place();
253                        result = Some(opaque);
254                    }
255                    _ => todo!("unsupported poke type"),
256                }
257            }
258            StackItem::StructField { key } => {
259                trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
260
261                let ps = match stack.front_mut().unwrap() {
262                    StackItem::FinishStruct { ps } => ps,
263                    _ => unreachable!(),
264                };
265
266                match ps.field_by_name(&key) {
267                    Ok((index, field_poke)) => {
268                        trace!("Found field, it's at index: \x1b[1;33m{index}\x1b[0m");
269
270                        stack.push_front(StackItem::AfterStructField { index });
271
272                        stack.push_front(StackItem::Value { poke: field_poke });
273                    }
274                    Err(_) => {
275                        trace!("No field named \x1b[1;36m{}\x1b[0m", key);
276                        return Err(parser.make_error(JsonParseErrorKind::UnknownField(key)));
277                    }
278                }
279            }
280            StackItem::AfterStructField { index } => {
281                trace!("After processing struct field at index: \x1b[1;33m{index}\x1b[0m");
282
283                let ps = match stack.front_mut().unwrap() {
284                    StackItem::FinishStruct { ps } => ps,
285                    _ => unreachable!(),
286                };
287
288                unsafe {
289                    ps.mark_initialized(index);
290                }
291
292                let next_key = parser.parse_object_key()?;
293                if let Some(next_key) = next_key {
294                    stack.push_front(StackItem::StructField { key: next_key });
295                }
296            }
297            StackItem::FinishStruct { ps } => {
298                trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
299
300                let opaque = ps.build_in_place();
301                result = Some(opaque);
302            }
303            StackItem::AfterListItem { item } => {
304                trace!("Processing array item at index");
305
306                let pl = match stack.front_mut().unwrap() {
307                    StackItem::FinishList { pl } => pl,
308                    _ => unreachable!(),
309                };
310                let item = unsafe { item.assume_init() };
311                unsafe {
312                    pl.push(item);
313                }
314                unsafe { std::alloc::dealloc(item.as_mut_byte_ptr(), pl.def().t.layout) };
315
316                let has_next = parser.parse_array_element()?;
317                if let Some(true) = has_next {
318                    let item_shape = pl.def().t;
319                    let item_data =
320                        OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
321                    let item_poke = unsafe { PokeUninit::unchecked_new(item_data, item_shape) };
322
323                    stack.push_front(StackItem::AfterListItem { item: item_data });
324                    stack.push_front(StackItem::Value { poke: item_poke });
325                }
326            }
327            StackItem::FinishList { pl } => {
328                trace!("Finished deserializing \x1b[1;36marray\x1b[0m");
329                let opaque = pl.build_in_place();
330                result = Some(opaque);
331            }
332            StackItem::AfterMapValue { mut key, value } => {
333                trace!("Processing hashmap key: \x1b[1;33m{}\x1b[0m", key);
334
335                let pm = match stack.front_mut().unwrap() {
336                    StackItem::FinishMap { pm } => pm,
337                    _ => unreachable!(),
338                };
339                let key_data = Opaque::new(&mut key);
340                let value = unsafe { value.assume_init() };
341                unsafe {
342                    pm.insert(key_data, value);
343                }
344                core::mem::forget(key); // key has been moved out of
345                unsafe { std::alloc::dealloc(value.as_mut_byte_ptr(), pm.def().v.layout) };
346
347                let next_key = parser.parse_object_key()?;
348                if let Some(next_key) = next_key {
349                    let value_shape = pm.def().v;
350                    let value_data =
351                        OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
352                    let value_poke = unsafe { PokeUninit::unchecked_new(value_data, value_shape) };
353
354                    stack.push_front(StackItem::AfterMapValue {
355                        key: next_key,
356                        value: value_data,
357                    });
358                    stack.push_front(StackItem::Value { poke: value_poke });
359                }
360            }
361            StackItem::FinishMap { pm } => {
362                trace!("Finished deserializing \x1b[1;36mhashmap\x1b[0m");
363                let opaque = pm.build_in_place();
364                result = Some(opaque);
365            }
366        }
367    }
368
369    result.ok_or_else(|| {
370        parser.make_error(JsonParseErrorKind::Custom(
371            "Unexpected end of input".to_string(),
372        ))
373    })
374}