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();
24        let shape = shape_desc.get();
25        trace!("Deserializing value with shape:\n{:?}", shape);
26
27        match &shape.innards {
28            Innards::Scalar(scalar) => {
29                let slot = partial.scalar_slot().expect("Scalar slot");
30                trace!("Deserializing \x1b[1;36mscalar\x1b[0m, \x1b[1;35m{scalar:?}\x1b[0m");
31
32                match scalar {
33                    Scalar::String => slot.fill(parser.parse_string()?),
34                    Scalar::U64 => slot.fill(parser.parse_u64()?),
35                    // Add other scalar types as needed
36                    _ => {
37                        warn!("Unsupported scalar type: {:?}", scalar);
38                        return Err(parser.make_error(JsonParseErrorKind::Custom(format!(
39                            "Unsupported scalar type: {:?}",
40                            scalar
41                        ))));
42                    }
43                }
44            }
45            Innards::Struct { .. } => {
46                trace!("Deserializing \x1b[1;36mstruct\x1b[0m");
47
48                let mut first = true;
49                while let Some(key) = if first {
50                    first = false;
51                    parser.expect_object_start()?
52                } else {
53                    parser.parse_object_key()?
54                } {
55                    trace!("Processing struct key: \x1b[1;33m{}\x1b[0m", key);
56                    let slot = partial
57                        .slot_by_name(&key)
58                        .map_err(|_| parser.make_error(JsonParseErrorKind::UnknownField(key)))?;
59
60                    let mut partial_field = Partial::alloc(slot.shape());
61                    deserialize_value(parser, &mut partial_field)?;
62                    slot.fill_from_partial(partial_field);
63                }
64                trace!("Finished deserializing \x1b[1;36mstruct\x1b[0m");
65
66                // TODO: this would be a good place to decide what to do about unset fields? Is this
67                // where we finally get to use `set_default`?
68            }
69            // Add support for other shapes (Array, Transparent) as needed
70            _ => {
71                error!("Unsupported shape: {:?}", shape.innards);
72                return Err(parser.make_error(JsonParseErrorKind::Custom(format!(
73                    "Unsupported shape: {:?}",
74                    shape.innards
75                ))));
76            }
77        }
78
79        trace!(
80            "Successfully deserialized value for shape: \x1b[1;32m{}\x1b[0m at address \x1b[1;34m{:?}\x1b[0m\n",
81            shape,
82            partial.addr()
83        );
84        Ok(())
85    }
86
87    let result = deserialize_value(&mut parser, partial);
88    match &result {
89        Ok(_) => {
90            trace!("JSON deserialization completed successfully");
91        }
92        Err(e) => {
93            error!("JSON deserialization failed: {}", e);
94        }
95    }
96    result
97}