1 #![cfg(feature = "alloc")]
2
3 use nom::{
4 branch::alt,
5 bytes::complete::{tag, take},
6 character::complete::{anychar, char, multispace0, none_of},
7 combinator::{map, map_opt, map_res, value, verify},
8 error::ParseError,
9 multi::{fold_many0, separated_list0},
10 number::complete::double,
11 sequence::{delimited, preceded, separated_pair},
12 IResult, Parser,
13 };
14
15 use std::collections::HashMap;
16
17 #[derive(Debug, PartialEq, Clone)]
18 pub enum JsonValue {
19 Null,
20 Bool(bool),
21 Str(String),
22 Num(f64),
23 Array(Vec<JsonValue>),
24 Object(HashMap<String, JsonValue>),
25 }
26
boolean(input: &str) -> IResult<&str, bool>27 fn boolean(input: &str) -> IResult<&str, bool> {
28 alt((value(false, tag("false")), value(true, tag("true"))))(input)
29 }
30
u16_hex(input: &str) -> IResult<&str, u16>31 fn u16_hex(input: &str) -> IResult<&str, u16> {
32 map_res(take(4usize), |s| u16::from_str_radix(s, 16))(input)
33 }
34
unicode_escape(input: &str) -> IResult<&str, char>35 fn unicode_escape(input: &str) -> IResult<&str, char> {
36 map_opt(
37 alt((
38 // Not a surrogate
39 map(verify(u16_hex, |cp| !(0xD800..0xE000).contains(cp)), |cp| {
40 cp as u32
41 }),
42 // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details
43 map(
44 verify(
45 separated_pair(u16_hex, tag("\\u"), u16_hex),
46 |(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low),
47 ),
48 |(high, low)| {
49 let high_ten = (high as u32) - 0xD800;
50 let low_ten = (low as u32) - 0xDC00;
51 (high_ten << 10) + low_ten + 0x10000
52 },
53 ),
54 )),
55 // Could be probably replaced with .unwrap() or _unchecked due to the verify checks
56 std::char::from_u32,
57 )(input)
58 }
59
character(input: &str) -> IResult<&str, char>60 fn character(input: &str) -> IResult<&str, char> {
61 let (input, c) = none_of("\"")(input)?;
62 if c == '\\' {
63 alt((
64 map_res(anychar, |c| {
65 Ok(match c {
66 '"' | '\\' | '/' => c,
67 'b' => '\x08',
68 'f' => '\x0C',
69 'n' => '\n',
70 'r' => '\r',
71 't' => '\t',
72 _ => return Err(()),
73 })
74 }),
75 preceded(char('u'), unicode_escape),
76 ))(input)
77 } else {
78 Ok((input, c))
79 }
80 }
81
string(input: &str) -> IResult<&str, String>82 fn string(input: &str) -> IResult<&str, String> {
83 delimited(
84 char('"'),
85 fold_many0(character, String::new, |mut string, c| {
86 string.push(c);
87 string
88 }),
89 char('"'),
90 )(input)
91 }
92
ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E>93 fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> {
94 delimited(multispace0, f, multispace0)
95 }
96
array(input: &str) -> IResult<&str, Vec<JsonValue>>97 fn array(input: &str) -> IResult<&str, Vec<JsonValue>> {
98 delimited(
99 char('['),
100 ws(separated_list0(ws(char(',')), json_value)),
101 char(']'),
102 )(input)
103 }
104
object(input: &str) -> IResult<&str, HashMap<String, JsonValue>>105 fn object(input: &str) -> IResult<&str, HashMap<String, JsonValue>> {
106 map(
107 delimited(
108 char('{'),
109 ws(separated_list0(
110 ws(char(',')),
111 separated_pair(string, ws(char(':')), json_value),
112 )),
113 char('}'),
114 ),
115 |key_values| key_values.into_iter().collect(),
116 )(input)
117 }
118
json_value(input: &str) -> IResult<&str, JsonValue>119 fn json_value(input: &str) -> IResult<&str, JsonValue> {
120 use JsonValue::*;
121
122 alt((
123 value(Null, tag("null")),
124 map(boolean, Bool),
125 map(string, Str),
126 map(double, Num),
127 map(array, Array),
128 map(object, Object),
129 ))(input)
130 }
131
json(input: &str) -> IResult<&str, JsonValue>132 fn json(input: &str) -> IResult<&str, JsonValue> {
133 ws(json_value).parse(input)
134 }
135
136 #[test]
json_string()137 fn json_string() {
138 assert_eq!(string("\"\""), Ok(("", "".to_string())));
139 assert_eq!(string("\"abc\""), Ok(("", "abc".to_string())));
140 assert_eq!(
141 string("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""),
142 Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01——def".to_string())),
143 );
144 assert_eq!(string("\"\\uD83D\\uDE10\""), Ok(("", "".to_string())));
145
146 assert!(string("\"").is_err());
147 assert!(string("\"abc").is_err());
148 assert!(string("\"\\\"").is_err());
149 assert!(string("\"\\u123\"").is_err());
150 assert!(string("\"\\uD800\"").is_err());
151 assert!(string("\"\\uD800\\uD800\"").is_err());
152 assert!(string("\"\\uDC00\"").is_err());
153 }
154
155 #[test]
json_object()156 fn json_object() {
157 use JsonValue::*;
158
159 let input = r#"{"a":42,"b":"x"}"#;
160
161 let expected = Object(
162 vec![
163 ("a".to_string(), Num(42.0)),
164 ("b".to_string(), Str("x".to_string())),
165 ]
166 .into_iter()
167 .collect(),
168 );
169
170 assert_eq!(json(input), Ok(("", expected)));
171 }
172
173 #[test]
json_array()174 fn json_array() {
175 use JsonValue::*;
176
177 let input = r#"[42,"x"]"#;
178
179 let expected = Array(vec![Num(42.0), Str("x".to_string())]);
180
181 assert_eq!(json(input), Ok(("", expected)));
182 }
183
184 #[test]
json_whitespace()185 fn json_whitespace() {
186 use JsonValue::*;
187
188 let input = r#"
189 {
190 "null" : null,
191 "true" :true ,
192 "false": false ,
193 "number" : 123e4 ,
194 "string" : " abc 123 " ,
195 "array" : [ false , 1 , "two" ] ,
196 "object" : { "a" : 1.0 , "b" : "c" } ,
197 "empty_array" : [ ] ,
198 "empty_object" : { }
199 }
200 "#;
201
202 assert_eq!(
203 json(input),
204 Ok((
205 "",
206 Object(
207 vec![
208 ("null".to_string(), Null),
209 ("true".to_string(), Bool(true)),
210 ("false".to_string(), Bool(false)),
211 ("number".to_string(), Num(123e4)),
212 ("string".to_string(), Str(" abc 123 ".to_string())),
213 (
214 "array".to_string(),
215 Array(vec![Bool(false), Num(1.0), Str("two".to_string())])
216 ),
217 (
218 "object".to_string(),
219 Object(
220 vec![
221 ("a".to_string(), Num(1.0)),
222 ("b".to_string(), Str("c".to_string())),
223 ]
224 .into_iter()
225 .collect()
226 )
227 ),
228 ("empty_array".to_string(), Array(vec![]),),
229 ("empty_object".to_string(), Object(HashMap::new()),),
230 ]
231 .into_iter()
232 .collect()
233 )
234 ))
235 );
236 }
237