facet_json_read/
deserialize.rs

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