facet_json/
deserialize.rs

1use std::num::NonZero;
2
3use crate::parser::{JsonParseErrorKind, JsonParseErrorWithContext, JsonParser};
4
5use facet_core::{Facet, Opaque, OpaqueUninit};
6use facet_reflect::{
7    PokeList, PokeMap, PokeOption, PokeStruct, PokeUninit, PokeValueUninit, ScalarType,
8};
9use log::trace;
10
11/// Deserializes a JSON string into a value of type `T` that implements `Facet`.
12///
13/// This function takes a JSON string representation and converts it into a Rust
14/// value of the specified type `T`. The type must implement the `Facet` trait
15/// to provide the necessary type information for deserialization.
16///
17/// # Parameters
18/// * `json` - A string slice containing the JSON to deserialize
19///
20/// # Returns
21/// * `Ok(T)` - The successfully deserialized value
22/// * `Err(JsonParseErrorWithContext)` - An error with context if deserialization fails
23///
24/// # Example
25/// ```
26/// # use facet::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::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.
104pub(crate) fn 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: PokeStruct<'mem>,
116        },
117        StructField {
118            key: String,
119        },
120        FinishSome {
121            po: PokeOption<'mem>,
122            some: OpaqueUninit<'mem>,
123        },
124        AfterStructField {
125            index: usize,
126        },
127        FinishList {
128            pl: PokeList<'mem>,
129        },
130        AfterListItem {
131            item: OpaqueUninit<'mem>,
132        },
133        FinishMap {
134            pm: PokeMap<'mem>,
135        },
136        AfterMapValue {
137            key: String,
138            value: OpaqueUninit<'mem>,
139        },
140    }
141
142    let mut result = None;
143    let mut stack = VecDeque::new();
144    stack.push_back(StackItem::Value { poke: root_poke });
145
146    while let Some(item) = stack.pop_front() {
147        match item {
148            StackItem::Value { poke } => {
149                let shape = poke.shape();
150                trace!("Deserializing {shape}");
151
152                match poke {
153                    PokeUninit::Scalar(pv) => {
154                        trace!("Deserializing \x1b[1;36mscalar\x1b[0m");
155                        fn aux<'input, 'mem>(
156                            parser: &mut JsonParser<'input>,
157                            pv: PokeValueUninit<'mem>,
158                        ) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>>
159                        {
160                            match pv.scalar_type() {
161                                Some(ScalarType::Bool) => {
162                                    let b = parser.parse_bool()?;
163                                    return Ok(pv.put(b));
164                                }
165                                Some(ScalarType::String) => {
166                                    let s = parser.parse_string()?;
167                                    let data = pv.put(s);
168                                    return Ok(data);
169                                }
170                                Some(ScalarType::F32) => {
171                                    let n = parser.parse_f64()? as f32;
172                                    return Ok(pv.put(n));
173                                }
174                                Some(ScalarType::F64) => {
175                                    let n = parser.parse_f64()?;
176                                    return Ok(pv.put(n));
177                                }
178                                _ => (),
179                            }
180
181                            // TODO: implement with match above
182                            unsigneds!(parser, pv, u8, u16, u32, u64, u128, usize);
183                            signeds!(parser, pv, i8, i16, i32, i64, i128, isize);
184
185                            panic!("Unknown scalar shape: {}", pv.shape());
186                        }
187
188                        result = Some(aux(parser, pv)?);
189                    }
190                    PokeUninit::Struct(ps) => {
191                        trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
192                        stack.push_front(StackItem::FinishStruct { ps });
193
194                        let first_key = parser.expect_object_start()?;
195                        if let Some(key) = first_key {
196                            stack.push_front(StackItem::StructField { key });
197                        }
198                    }
199                    PokeUninit::List(list_uninit) => {
200                        trace!("Deserializing \x1b[1;36marray\x1b[0m");
201                        parser.expect_array_start()?;
202
203                        let pl = list_uninit.init(None).unwrap_or_else(|_| {
204                            panic!("Failed to initialize list");
205                        });
206
207                        let has_element = parser.parse_array_element()?;
208
209                        if let Some(true) = has_element {
210                            let item_shape = pl.def().t;
211                            let item_data =
212                                OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
213                            let item_poke =
214                                unsafe { PokeUninit::unchecked_new(item_data, item_shape) };
215
216                            stack.push_front(StackItem::FinishList { pl });
217                            stack.push_front(StackItem::AfterListItem { item: item_data });
218                            stack.push_front(StackItem::Value { poke: item_poke });
219                        } else {
220                            stack.push_front(StackItem::FinishList { pl });
221                        }
222                    }
223                    PokeUninit::Map(map_uninit) => {
224                        trace!("Deserializing \x1b[1;36mhashmap\x1b[0m");
225                        let first_key = parser.expect_object_start()?;
226
227                        let pm = map_uninit.init(None).unwrap_or_else(|_| {
228                            panic!("Failed to initialize map"); // TODO: map errors
229                        });
230
231                        if let Some(key) = first_key {
232                            let value_shape = pm.def().v;
233                            let value_data =
234                                OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
235                            let value_poke =
236                                unsafe { PokeUninit::unchecked_new(value_data, value_shape) };
237
238                            stack.push_front(StackItem::FinishMap { pm });
239                            stack.push_front(StackItem::AfterMapValue {
240                                key,
241                                value: value_data,
242                            });
243                            stack.push_front(StackItem::Value { poke: value_poke });
244                        } else {
245                            stack.push_front(StackItem::FinishMap { pm });
246                        }
247                    }
248                    PokeUninit::Enum(pe) => {
249                        trace!("Deserializing \x1b[1;36menum\x1b[0m");
250                        let variant_str = parser.parse_string()?;
251
252                        let pe = pe.set_variant_by_name(&variant_str).map_err(|_| {
253                            parser.make_error(JsonParseErrorKind::Custom(format!(
254                                "Invalid enum variant: {}",
255                                variant_str
256                            )))
257                        })?;
258
259                        trace!("Finished deserializing \x1b[1;36menum\x1b[0m");
260                        let opaque = pe.build_in_place();
261                        result = Some(opaque);
262                    }
263                    PokeUninit::Option(po) => {
264                        trace!("Deserializing \x1b[1;36moption\x1b[0m");
265                        let po = unsafe { po.init_none() };
266                        if let Ok(()) = parser.parse_null() {
267                            trace!("Finished deserializing \x1b[1;36mNone\x1b[0m");
268                            result = Some(po.build_in_place());
269                        } else {
270                            let some_shape = po.def().t;
271                            let some_data =
272                                OpaqueUninit::new(unsafe { std::alloc::alloc(some_shape.layout) });
273                            let some_poke =
274                                unsafe { PokeUninit::unchecked_new(some_data, some_shape) };
275
276                            stack.push_front(StackItem::FinishSome {
277                                po,
278                                some: some_data,
279                            });
280                            stack.push_front(StackItem::Value { poke: some_poke });
281                        }
282                    }
283                    _ => todo!("unsupported poke type"),
284                }
285            }
286            StackItem::StructField { key } => {
287                trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
288
289                let ps = match stack.front_mut().unwrap() {
290                    StackItem::FinishStruct { ps } => ps,
291                    _ => unreachable!(),
292                };
293
294                match ps.field_by_name(&key) {
295                    Ok((index, field_poke)) => {
296                        trace!("Found field, it's at index: \x1b[1;33m{index}\x1b[0m");
297
298                        stack.push_front(StackItem::AfterStructField { index });
299
300                        stack.push_front(StackItem::Value { poke: field_poke });
301                    }
302                    Err(_) => {
303                        trace!("No field named \x1b[1;36m{}\x1b[0m", key);
304                        return Err(parser.make_error(JsonParseErrorKind::UnknownField(key)));
305                    }
306                }
307            }
308            StackItem::FinishSome { po, some } => {
309                trace!("Finished deserializing \x1b[1;36mSome\x1b[0m");
310                let layout = po.def().t.layout;
311                result = Some(unsafe {
312                    po.replace_with_some_opaque(some.assume_init().as_const())
313                        .build_in_place()
314                });
315                unsafe { std::alloc::dealloc(some.as_mut_bytes(), layout) };
316            }
317            StackItem::AfterStructField { index } => {
318                trace!("After processing struct field at index: \x1b[1;33m{index}\x1b[0m");
319
320                let ps = match stack.front_mut().unwrap() {
321                    StackItem::FinishStruct { ps } => ps,
322                    _ => unreachable!(),
323                };
324
325                unsafe {
326                    ps.mark_initialized(index);
327                }
328
329                let next_key = parser.parse_object_key()?;
330                if let Some(next_key) = next_key {
331                    stack.push_front(StackItem::StructField { key: next_key });
332                }
333            }
334            StackItem::FinishStruct { ps } => {
335                trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
336
337                let opaque = ps.build_in_place();
338                result = Some(opaque);
339            }
340            StackItem::AfterListItem { item } => {
341                trace!("Processing array item at index");
342
343                let pl = match stack.front_mut().unwrap() {
344                    StackItem::FinishList { pl } => pl,
345                    _ => unreachable!(),
346                };
347                let item = unsafe { item.assume_init() };
348                unsafe {
349                    pl.push(item);
350                }
351                unsafe { std::alloc::dealloc(item.as_mut_byte_ptr(), pl.def().t.layout) };
352
353                let has_next = parser.parse_array_element()?;
354                if let Some(true) = has_next {
355                    let item_shape = pl.def().t;
356                    let item_data =
357                        OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
358                    let item_poke = unsafe { PokeUninit::unchecked_new(item_data, item_shape) };
359
360                    stack.push_front(StackItem::AfterListItem { item: item_data });
361                    stack.push_front(StackItem::Value { poke: item_poke });
362                }
363            }
364            StackItem::FinishList { pl } => {
365                trace!("Finished deserializing \x1b[1;36marray\x1b[0m");
366                let opaque = pl.build_in_place();
367                result = Some(opaque);
368            }
369            StackItem::AfterMapValue { mut key, value } => {
370                trace!("Processing hashmap key: \x1b[1;33m{}\x1b[0m", key);
371
372                let pm = match stack.front_mut().unwrap() {
373                    StackItem::FinishMap { pm } => pm,
374                    _ => unreachable!(),
375                };
376                let key_data = Opaque::new(&mut key);
377                let value = unsafe { value.assume_init() };
378                unsafe {
379                    pm.insert(key_data, value);
380                }
381                core::mem::forget(key); // key has been moved out of
382                unsafe { std::alloc::dealloc(value.as_mut_byte_ptr(), pm.def().v.layout) };
383
384                let next_key = parser.parse_object_key()?;
385                if let Some(next_key) = next_key {
386                    let value_shape = pm.def().v;
387                    let value_data =
388                        OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
389                    let value_poke = unsafe { PokeUninit::unchecked_new(value_data, value_shape) };
390
391                    stack.push_front(StackItem::AfterMapValue {
392                        key: next_key,
393                        value: value_data,
394                    });
395                    stack.push_front(StackItem::Value { poke: value_poke });
396                }
397            }
398            StackItem::FinishMap { pm } => {
399                trace!("Finished deserializing \x1b[1;36mhashmap\x1b[0m");
400                let opaque = pm.build_in_place();
401                result = Some(opaque);
402            }
403        }
404    }
405
406    result.ok_or_else(|| {
407        parser.make_error(JsonParseErrorKind::Custom(
408            "Unexpected end of input".to_string(),
409        ))
410    })
411}