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}