shape/
from_json.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use serde_json::Value as JSON;
use serde_json_bytes::Value as JSONBytes;

use super::Shape;
use super::ShapeCase;

impl Shape {
    /// Derive a [`Shape`] from a JSON value, which is almost a lossless
    /// conversion except that floating point literals get the general
    /// [`ShapeCase::Float`] shape, ignoring their particular values.
    ///
    /// Note that all locations will be empty, because [`serde_json`] doesn't track locations.
    ///
    /// # Panics
    ///
    /// If the JSON value can't be converted into a [`serde_json_bytes::Value`]
    #[must_use]
    pub fn from_json(json: &JSON) -> Self {
        Shape::new(ShapeCase::from_json(json), [])
    }

    /// Derive a [`Shape`] from a JSON value using the [`serde_json_bytes`] crate.
    ///
    /// Note that all locations will be empty, because [`serde_json_bytes`] doesn't track locations.
    pub fn from_json_bytes(json: &JSONBytes) -> Self {
        Shape::new(ShapeCase::from_json_bytes(json), [])
    }
}

impl ShapeCase {
    /// Derive a [`ShapeCase`] from a [`serde_json::Value`].
    ///
    /// # Panics
    ///
    /// If the [`serde_json::Value`] can't be converted into a [`serde_json_bytes::Value`]
    #[must_use]
    pub fn from_json(json: &JSON) -> Self {
        Self::from_json_bytes(
            &json
                .to_string()
                .parse()
                .expect("serde_json_bytes doesn't match serde_json"),
        )
    }

    pub fn from_json_bytes(json: &JSONBytes) -> Self {
        match json {
            JSONBytes::Bool(b) => Self::Bool(Some(*b)),
            JSONBytes::String(s) => Self::String(Some(s.as_str().to_string())),
            JSONBytes::Number(n) => {
                if let Some(i) = n.as_i64() {
                    Self::Int(Some(i))
                } else {
                    Self::Float
                }
            }
            JSONBytes::Null => Self::Null,
            JSONBytes::Array(arr) => {
                let mut prefix = Vec::with_capacity(arr.len());
                for item in arr {
                    prefix.push(Shape::from_json_bytes(item));
                }
                Self::Array {
                    prefix,
                    tail: Shape::none(),
                }
            }
            JSONBytes::Object(obj) => {
                let mut fields = Shape::empty_map();
                for (key, value) in obj {
                    fields.insert(key.as_str().to_string(), Shape::from_json_bytes(value));
                }
                Self::Object {
                    fields,
                    rest: Shape::none(),
                }
            }
        }
    }
}