valu3/parser/json/
mod.rs

1use crate::prelude::*;
2use pest::Parser;
3use std::collections::HashMap;
4
5#[derive(Parser)]
6#[grammar = "parser/json/json.pest"]
7struct JSONParser;
8
9use pest::iterators::Pair;
10
11impl Value {
12    pub fn json_to_value(str: &str) -> Result<Value, Error> {
13        let value = match JSONParser::parse(Rule::json, str.trim()) {
14            Ok(mut pairs) => match pairs.next() {
15                Some(pair) => Self::json_parse_value_inner(pair),
16                None => return Err(Error::NonParseble),
17            },
18            Err(msg) => return Err(Error::NonParsebleMsg(msg.to_string())),
19        };
20        Ok(value)
21    }
22
23    fn json_parse_value_inner(pair: Pair<Rule>) -> Self {
24        match pair.as_rule() {
25            Rule::object => {
26                let map = pair
27                    .into_inner()
28                    .map(|pair| {
29                        let mut inner_rules = pair.into_inner();
30                        let name = inner_rules
31                            .next()
32                            .unwrap()
33                            .into_inner()
34                            .next()
35                            .unwrap()
36                            .as_str()
37                            .to_string();
38                        let value = Self::json_parse_value_inner(inner_rules.next().unwrap());
39                        (name, value)
40                    })
41                    .collect::<HashMap<String, Value>>();
42
43                Self::from(map)
44            }
45            Rule::array => Self::from(
46                pair.into_inner()
47                    .map(Self::json_parse_value_inner)
48                    .collect::<Vec<_>>(),
49            ),
50            Rule::string => Self::from(StringB::from(pair.into_inner().next().unwrap().as_str())),
51            Rule::number => Self::from(Number::try_from(pair.as_str()).unwrap()),
52            Rule::boolean => Self::Boolean(pair.as_str().parse().unwrap()),
53            Rule::null => Self::Null,
54            Rule::json
55            | Rule::EOI
56            | Rule::key_value_pair
57            | Rule::value
58            | Rule::inner
59            | Rule::char
60            | Rule::WHITESPACE => Self::Undefined,
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use crate::prelude::*;
68    use std::collections::HashMap;
69
70    #[test]
71    fn json() {
72        let raw: &str = "{
73        \"test\": true,
74        \"test2\": \"ok\",
75        \"test3\": [0, 1]
76       }";
77
78        let compare = Value::from({
79            let mut map = HashMap::new();
80            map.insert("test".to_string(), true.to_value());
81            map.insert("test2".to_string(), "ok".to_value());
82            map.insert("test3".to_string(), Value::from(vec![0, 1]));
83            map
84        });
85
86        assert_eq!(Value::json_to_value(raw), Ok(compare));
87    }
88
89    #[test]
90    fn array() {
91        let raw = "[0, true, null, \"ok\"]";
92
93        let compare = {
94            let mut list = Vec::new();
95            list.push(Value::Number(Number::from(0)));
96            list.push(Value::Boolean(true));
97            list.push(Value::Null);
98            list.push(Value::String(StringB::from("ok")));
99            Value::from(list)
100        };
101
102        assert_eq!(Value::json_to_value(raw), Ok(compare));
103    }
104
105    #[test]
106    fn number() {
107        let int = "0";
108        let float = "1.0";
109
110        assert_eq!(
111            Value::json_to_value(int),
112            Ok(Value::Number(Number::from(0)))
113        );
114        assert_eq!(
115            Value::json_to_value(float),
116            Ok(Value::Number(Number::from(1.0)))
117        );
118    }
119
120    #[test]
121    fn string() {
122        let string = r#""string""#;
123
124        assert_eq!(
125            Value::json_to_value(string),
126            Ok(Value::String(StringB::from("string")))
127        );
128    }
129
130    #[test]
131    fn null() {
132        let null = "null";
133
134        assert_eq!(Value::json_to_value(null), Ok(Value::Null));
135    }
136    #[test]
137    fn boolean() {
138        let boolean = "true";
139
140        assert_eq!(Value::json_to_value(boolean), Ok(Value::Boolean(true)));
141    }
142
143    #[test]
144    fn all() {
145        let boolean = Value::json_to_value("true").unwrap();
146        let float = Value::json_to_value("3.14").unwrap();
147        let json = Value::json_to_value(r#"{"item": 3.14}"#).unwrap();
148        let array = Value::json_to_value(r#"[1,2,3]"#).unwrap();
149        let null = Value::json_to_value("null").unwrap();
150        let string = Value::json_to_value(r#""123""#).unwrap();
151
152        assert_eq!(boolean, true.to_value());
153        assert_eq!(float, 3.14.to_value());
154        assert_eq!(json, Value::from(vec![("item", 3.14)]));
155        assert_eq!(array, vec![1, 2, 3].to_value());
156        assert_eq!(null, Value::Null);
157        assert_eq!(string, "123".to_value());
158    }
159}