facet_json_read/
deserialize.rs

1use crate::parser::{JsonParseErrorKind, JsonParseErrorWithContext, JsonParser};
2
3use facet_core::{Facet, Opaque, OpaqueUninit};
4use facet_poke::Poke;
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_core::Facet;
23/// # use facet_derive::Facet;
24/// # use facet_core 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 = pv.put(s);
101                            data
102                        } else if pv.shape().is_type::<bool>() {
103                            let b = parser.parse_bool()?;
104                            pv.put(b)
105                        // Unsigned integers
106                        } else if pv.shape().is_type::<u8>() {
107                            let n = parser.parse_u64()? as u8;
108                            pv.put(n)
109                        } else if pv.shape().is_type::<u16>() {
110                            let n = parser.parse_u64()? as u16;
111                            pv.put(n)
112                        } else if pv.shape().is_type::<u32>() {
113                            let n = parser.parse_u64()? as u32;
114                            pv.put(n)
115                        } else if pv.shape().is_type::<u64>() {
116                            let n = parser.parse_u64()?;
117                            pv.put(n)
118                        } else if pv.shape().is_type::<u128>() {
119                            let n = parser.parse_u64()? as u128;
120                            pv.put(n)
121                        // Signed integers
122                        } else if pv.shape().is_type::<i8>() {
123                            let n = parser.parse_i64()? as i8;
124                            pv.put(n)
125                        } else if pv.shape().is_type::<i16>() {
126                            let n = parser.parse_i64()? as i16;
127                            pv.put(n)
128                        } else if pv.shape().is_type::<i32>() {
129                            let n = parser.parse_i64()? as i32;
130                            pv.put(n)
131                        } else if pv.shape().is_type::<i64>() {
132                            let n = parser.parse_i64()?;
133                            pv.put(n)
134                        } else if pv.shape().is_type::<i128>() {
135                            let n = parser.parse_i64()? as i128;
136                            pv.put(n)
137                        // Floating point
138                        } else if pv.shape().is_type::<f32>() {
139                            let n = parser.parse_f64()? as f32;
140                            pv.put(n)
141                        } else if pv.shape().is_type::<f64>() {
142                            let n = parser.parse_f64()?;
143                            pv.put(n)
144                        } else {
145                            panic!("Unknown scalar shape: {}", pv.shape());
146                        };
147                        result = Some(opaque);
148                    }
149                    Poke::Struct(ps) => {
150                        trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
151                        stack.push_front(StackItem::FinishStruct { ps });
152
153                        let first_key = parser.expect_object_start()?;
154                        if let Some(key) = first_key {
155                            stack.push_front(StackItem::StructField { key });
156                        }
157                    }
158                    Poke::List(list_uninit) => {
159                        trace!("Deserializing \x1b[1;36marray\x1b[0m");
160                        parser.expect_array_start()?;
161
162                        let pl = list_uninit.init(None).unwrap_or_else(|_| {
163                            panic!("Failed to initialize list");
164                        });
165
166                        let has_element = parser.parse_array_element()?;
167
168                        if let Some(true) = has_element {
169                            let item_shape = pl.def().t;
170                            let item_data =
171                                OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
172                            let item_poke = unsafe { Poke::unchecked_new(item_data, item_shape) };
173
174                            stack.push_front(StackItem::FinishList { pl });
175                            stack.push_front(StackItem::AfterListItem { item: item_data });
176                            stack.push_front(StackItem::Value { poke: item_poke });
177                        } else {
178                            stack.push_front(StackItem::FinishList { pl });
179                        }
180                    }
181                    Poke::Map(map_uninit) => {
182                        trace!("Deserializing \x1b[1;36mhashmap\x1b[0m");
183                        let first_key = parser.expect_object_start()?;
184
185                        let pm = map_uninit.init(None).unwrap_or_else(|_| {
186                            panic!("Failed to initialize map"); // TODO: map errors
187                        });
188
189                        if let Some(key) = first_key {
190                            let value_shape = pm.def().v;
191                            let value_data =
192                                OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
193                            let value_poke =
194                                unsafe { Poke::unchecked_new(value_data, value_shape) };
195
196                            stack.push_front(StackItem::FinishMap { pm });
197                            stack.push_front(StackItem::AfterMapValue {
198                                key,
199                                value: value_data,
200                            });
201                            stack.push_front(StackItem::Value { poke: value_poke });
202                        } else {
203                            stack.push_front(StackItem::FinishMap { pm });
204                        }
205                    }
206                    Poke::Enum(pe) => {
207                        trace!("Deserializing \x1b[1;36menum\x1b[0m");
208                        let variant_str = parser.parse_string()?;
209
210                        let pe = pe.set_variant_by_name(&variant_str).map_err(|_| {
211                            parser.make_error(JsonParseErrorKind::Custom(format!(
212                                "Invalid enum variant: {}",
213                                variant_str
214                            )))
215                        })?;
216
217                        trace!("Finished deserializing \x1b[1;36menum\x1b[0m");
218                        let opaque = pe.build_in_place();
219                        result = Some(opaque);
220                    }
221                    _ => todo!("unsupported poke type"),
222                }
223            }
224            StackItem::StructField { key } => {
225                trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
226
227                let ps = match stack.front_mut().unwrap() {
228                    StackItem::FinishStruct { ps } => ps,
229                    _ => unreachable!(),
230                };
231
232                match ps.field_by_name(&key) {
233                    Ok((index, field_poke)) => {
234                        trace!("Found field, it's at index: \x1b[1;33m{index}\x1b[0m");
235
236                        stack.push_front(StackItem::AfterStructField { index });
237
238                        stack.push_front(StackItem::Value { poke: field_poke });
239                    }
240                    Err(_) => {
241                        trace!("No field named \x1b[1;36m{}\x1b[0m", key);
242                        return Err(parser.make_error(JsonParseErrorKind::UnknownField(key)));
243                    }
244                }
245            }
246            StackItem::AfterStructField { index } => {
247                trace!("After processing struct field at index: \x1b[1;33m{index}\x1b[0m");
248
249                let ps = match stack.front_mut().unwrap() {
250                    StackItem::FinishStruct { ps } => ps,
251                    _ => unreachable!(),
252                };
253
254                unsafe {
255                    ps.mark_initialized(index);
256                }
257
258                let next_key = parser.parse_object_key()?;
259                if let Some(next_key) = next_key {
260                    stack.push_front(StackItem::StructField { key: next_key });
261                }
262            }
263            StackItem::FinishStruct { ps } => {
264                trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
265
266                let opaque = ps.build_in_place();
267                result = Some(opaque);
268            }
269            StackItem::AfterListItem { item } => {
270                trace!("Processing array item at index");
271
272                let pl = match stack.front_mut().unwrap() {
273                    StackItem::FinishList { pl } => pl,
274                    _ => unreachable!(),
275                };
276                let item = unsafe { item.assume_init() };
277                unsafe {
278                    pl.push(item);
279                }
280                unsafe { std::alloc::dealloc(item.as_mut_byte_ptr(), pl.def().t.layout) };
281
282                let has_next = parser.parse_array_element()?;
283                if let Some(true) = has_next {
284                    let item_shape = pl.def().t;
285                    let item_data =
286                        OpaqueUninit::new(unsafe { std::alloc::alloc(item_shape.layout) });
287                    let item_poke = unsafe { Poke::unchecked_new(item_data, item_shape) };
288
289                    stack.push_front(StackItem::AfterListItem { item: item_data });
290                    stack.push_front(StackItem::Value { poke: item_poke });
291                }
292            }
293            StackItem::FinishList { pl } => {
294                trace!("Finished deserializing \x1b[1;36marray\x1b[0m");
295                let opaque = pl.build_in_place();
296                result = Some(opaque);
297            }
298            StackItem::AfterMapValue { mut key, value } => {
299                trace!("Processing hashmap key: \x1b[1;33m{}\x1b[0m", key);
300
301                let pm = match stack.front_mut().unwrap() {
302                    StackItem::FinishMap { pm } => pm,
303                    _ => unreachable!(),
304                };
305                let key_data = Opaque::new(&mut key);
306                let value = unsafe { value.assume_init() };
307                unsafe {
308                    pm.insert(key_data, value);
309                }
310                core::mem::forget(key); // key has been moved out of
311                unsafe { std::alloc::dealloc(value.as_mut_byte_ptr(), pm.def().v.layout) };
312
313                let next_key = parser.parse_object_key()?;
314                if let Some(next_key) = next_key {
315                    let value_shape = pm.def().v;
316                    let value_data =
317                        OpaqueUninit::new(unsafe { std::alloc::alloc(value_shape.layout) });
318                    let value_poke = unsafe { Poke::unchecked_new(value_data, value_shape) };
319
320                    stack.push_front(StackItem::AfterMapValue {
321                        key: next_key,
322                        value: value_data,
323                    });
324                    stack.push_front(StackItem::Value { poke: value_poke });
325                }
326            }
327            StackItem::FinishMap { pm } => {
328                trace!("Finished deserializing \x1b[1;36mhashmap\x1b[0m");
329                let opaque = pm.build_in_place();
330                result = Some(opaque);
331            }
332        }
333    }
334
335    result.ok_or_else(|| {
336        parser.make_error(JsonParseErrorKind::Custom(
337            "Unexpected end of input".to_string(),
338        ))
339    })
340}