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