shapely_json/
lib.rs

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