facet_json/
from_json.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::from_str(json).unwrap();
29/// ```
30pub fn from_str<T: Facet>(json: &str) -> Result<T, JsonParseErrorWithContext<'_>> {
31    // Allocate a Poke for type T
32    let (poke, _guard) = Poke::alloc::<T>();
33
34    // Deserialize the JSON into the Poke
35    let opaque = from_str_opaque(poke, json)?;
36
37    // Convert the Opaque to the concrete type T
38    let result = unsafe { opaque.read::<T>() };
39
40    Ok(result)
41}
42
43/// Deserialize a `Poke` object from a JSON string.
44pub fn from_str_opaque<'input, 'mem>(
45    poke: Poke<'mem>,
46    json: &'input str,
47) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>> {
48    trace!("Starting JSON deserialization");
49    let mut parser = JsonParser::new(json);
50    deserialize_value(&mut parser, poke)
51}
52
53fn deserialize_value<'input, 'mem>(
54    parser: &mut JsonParser<'input>,
55    poke: Poke<'mem>,
56) -> Result<Opaque<'mem>, JsonParseErrorWithContext<'input>> {
57    let shape = poke.shape();
58    trace!("Deserializing {:?}", shape);
59
60    let opaque = match poke {
61        Poke::Scalar(pv) => {
62            trace!("Deserializing \x1b[1;36mscalar\x1b[0m");
63            if pv.shape().is_type::<String>() {
64                let s = parser.parse_string()?;
65                let data = unsafe { pv.put(OpaqueConst::from_ref(&s)) };
66                std::mem::forget(s);
67                data
68            } else if pv.shape().is_type::<u64>() {
69                let n = parser.parse_u64()?;
70                unsafe { pv.put(OpaqueConst::from_ref(&n)) }
71            } else {
72                panic!("Unknown scalar shape: {}", pv.shape());
73            }
74        }
75        Poke::Struct(mut ps) => {
76            trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
77
78            let mut first = true;
79            while let Some(key) = if first {
80                first = false;
81                parser.expect_object_start()?
82            } else {
83                parser.parse_object_key()?
84            } {
85                trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
86                let index = match ps.field_by_name(&key) {
87                    Ok((index, field_poke)) => {
88                        deserialize_value(parser, field_poke)?;
89                        index
90                    }
91                    Err(_) => {
92                        return Err(parser.make_error(JsonParseErrorKind::UnknownField(key)));
93                    }
94                };
95                unsafe { ps.mark_initialized(index) };
96            }
97            trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
98            ps.build_in_place()
99        }
100        Poke::List(list_uninit) => {
101            trace!("Deserializing \x1b[1;36marray\x1b[0m");
102
103            // Parse array start
104            parser.expect_array_start()?;
105
106            // Initialize the list with no size hint
107            let mut pl = list_uninit.init(None).unwrap_or_else(|_| {
108                panic!("Failed to initialize list");
109            });
110
111            let mut index = 0;
112            while let Some(has_element) = parser.parse_array_element()? {
113                if !has_element {
114                    break;
115                }
116
117                trace!("Processing array item at index: \x1b[1;33m{}\x1b[0m", index);
118
119                let data = OpaqueUninit::new(unsafe { std::alloc::alloc(shape.layout) });
120                let item_poke = unsafe { Poke::unchecked_new(data, shape) };
121
122                // Deserialize the item
123                deserialize_value(parser, item_poke)?;
124
125                // Add the item to the list
126                unsafe {
127                    pl.push(data.assume_init());
128                }
129
130                index += 1;
131            }
132
133            trace!(
134                "Finished deserializing \x1b[1;36marray\x1b[0m with {} items",
135                index
136            );
137            pl.build_in_place()
138        }
139        Poke::Map(pm) => {
140            trace!("Deserializing \x1b[1;36mhashmap\x1b[0m");
141
142            // Parse object start and get first key if it exists
143            let first_key = parser.expect_object_start()?;
144
145            // Initialize the map with no size hint
146            let mut pm = pm
147                .init(None)
148                .unwrap_or_else(|_| panic!("Failed to initialize map")); // TODO: map errors
149
150            // Process each key-value pair in the JSON object
151            let mut current_key = first_key;
152            while let Some(key) = current_key {
153                trace!("Processing hashmap key: \x1b[1;33m{}\x1b[0m", key);
154
155                // Create a poke for the key (string type)
156                let key_data = OpaqueUninit::new(unsafe { std::alloc::alloc(pm.def.k.layout) });
157                let key_poke = unsafe { Poke::unchecked_new(key_data, pm.def.k) };
158                let scalar_key_poke = key_poke.into_scalar();
159                scalar_key_poke.parse(&key).unwrap(); // TODO: map errors
160
161                // Create a poke for the value based on map def
162                let value_data = OpaqueUninit::new(unsafe { std::alloc::alloc(pm.def.v.layout) });
163                let value_poke = unsafe { Poke::unchecked_new(value_data, pm.def.v) };
164
165                // Deserialize the value
166                deserialize_value(parser, value_poke)?;
167
168                // Insert the key-value pair into the hashmap
169                unsafe {
170                    pm.insert(key_data.assume_init(), value_data.assume_init());
171                }
172
173                // Get the next key
174                current_key = parser.parse_object_key()?;
175            }
176
177            trace!("Finished deserializing \x1b[1;36mhashmap\x1b[0m");
178            pm.build_in_place()
179        }
180        Poke::Enum(pe) => {
181            trace!("Deserializing \x1b[1;36menum\x1b[0m");
182            // Assuming enums are serialized as JSON strings representing the variant name
183            let variant_str = parser.parse_string()?;
184
185            let pe = pe.set_variant_by_name(&variant_str).map_err(|_| {
186                parser.make_error(JsonParseErrorKind::Custom(format!(
187                    "Invalid enum variant: {}",
188                    variant_str
189                )))
190            })?;
191
192            trace!("Finished deserializing \x1b[1;36menum\x1b[0m");
193            pe.build_in_place()
194        }
195    };
196    Ok(opaque)
197}