shapely_json/
lib.rs

1use parser::{JsonParseErrorKind, JsonParseErrorWithContext, JsonParser};
2use shapely::{error, trace, warn, Partial};
3
4mod parser;
5
6#[cfg(test)]
7mod tests;
8
9pub fn from_json<'input>(
10    partial: &mut Partial,
11    json: &'input str,
12) -> Result<(), JsonParseErrorWithContext<'input>> {
13    use shapely::{Innards, Scalar};
14
15    trace!("Starting JSON deserialization");
16    let mut parser = JsonParser::new(json);
17
18    fn deserialize_value<'input>(
19        parser: &mut JsonParser<'input>,
20        partial: &mut Partial,
21    ) -> Result<(), JsonParseErrorWithContext<'input>> {
22        let shape_desc = partial.shape_desc();
23        let shape = shape_desc.get();
24        trace!("Deserializing value with shape:\n{:?}", shape);
25
26        match &shape.innards {
27            Innards::Scalar(scalar) => {
28                match scalar {
29                    Scalar::String => {
30                        trace!("Deserializing String");
31                        let s = parser.parse_string()?;
32                        trace!("Deserialized String: {}", s);
33                        partial.scalar_slot().expect("String scalar slot").fill(s);
34                    }
35                    Scalar::U64 => {
36                        trace!("Deserializing U64");
37                        let n = parser.parse_u64()?;
38                        partial.scalar_slot().expect("U64 scalar slot").fill(n);
39                        trace!("Deserialized U64: {}", n);
40                    }
41                    // Add other scalar types as needed
42                    _ => {
43                        warn!("Unsupported scalar type: {:?}", scalar);
44                        return Err(parser.make_error(JsonParseErrorKind::Custom(format!(
45                            "Unsupported scalar type: {:?}",
46                            scalar
47                        ))));
48                    }
49                }
50            }
51            Innards::Struct { fields } => {
52                trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
53                if let Some(first_key) = parser.expect_object_start()? {
54                    trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", first_key);
55                    if let Some(field) = fields.iter().find(|f| f.name == first_key).copied() {
56                        let mut partial_field = Partial::alloc(field.shape);
57                        trace!("Deserializing field: \x1b[1;32m{}\x1b[0m", field.name);
58                        deserialize_value(parser, &mut partial_field)?;
59                        let slot = partial.slot(field).expect("Field slot");
60                        slot.fill_from_partial(partial_field);
61                    } else {
62                        warn!("Unknown field: \x1b[1;31m{}\x1b[0m, skipping", first_key);
63                        parser.skip_value()?;
64                    }
65                }
66                while let Some(key) = parser.parse_object_key()? {
67                    trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
68                    if let Some(field) = fields.iter().find(|f| f.name == key).copied() {
69                        // FIXME: we could definitely optimize this — the struct is already
70                        // allocated at this stage, so we could grab the address of its field.
71                        let mut partial_field = Partial::alloc(field.shape);
72                        trace!("Deserializing field: \x1b[1;32m{}\x1b[0m", field.name);
73                        deserialize_value(parser, &mut partial_field)?;
74                        let slot = partial.slot(field).expect("Field slot");
75                        slot.fill_from_partial(partial_field);
76                    } else {
77                        warn!("Unknown field: \x1b[1;31m{}\x1b[0m, skipping", key);
78                        parser.skip_value()?;
79                    }
80                }
81                trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
82            }
83            // Add support for other shapes (Array, Transparent) as needed
84            _ => {
85                error!("Unsupported shape: {:?}", shape.innards);
86                return Err(parser.make_error(JsonParseErrorKind::Custom(format!(
87                    "Unsupported shape: {:?}",
88                    shape.innards
89                ))));
90            }
91        }
92
93        trace!(
94            "Successfully deserialized value for shape: \x1b[1;32m{}\x1b[0m at address \x1b[1;34m{:?}\x1b[0m\n",
95            shape.name,
96            partial.addr()
97        );
98        Ok(())
99    }
100
101    let result = deserialize_value(&mut parser, partial);
102    match &result {
103        Ok(_) => {
104            trace!("JSON deserialization completed successfully");
105        }
106        Err(e) => {
107            error!("JSON deserialization failed: {}", e);
108        }
109    }
110    result
111}