1 #![cfg(feature = "alloc")]
2
3 use nom::{
4 branch::alt,
5 bytes::complete::{escaped, tag, take_while},
6 character::complete::{alphanumeric1 as alphanumeric, char, one_of},
7 combinator::{cut, map},
8 error::{context, ParseError},
9 multi::separated_list0,
10 number::complete::double,
11 sequence::{preceded, separated_pair, terminated},
12 IResult,
13 };
14 use std::collections::HashMap;
15
16 use std::cell::Cell;
17 use std::str;
18
19 #[derive(Clone, Debug)]
20 pub struct JsonValue<'a, 'b> {
21 input: &'a str,
22 pub offset: &'b Cell<usize>,
23 }
24
25 impl<'a, 'b: 'a> JsonValue<'a, 'b> {
new(input: &'a str, offset: &'b Cell<usize>) -> JsonValue<'a, 'b>26 pub fn new(input: &'a str, offset: &'b Cell<usize>) -> JsonValue<'a, 'b> {
27 JsonValue { input, offset }
28 }
29
offset(&self, input: &'a str)30 pub fn offset(&self, input: &'a str) {
31 let offset = input.as_ptr() as usize - self.input.as_ptr() as usize;
32 self.offset.set(offset);
33 }
34
data(&self) -> &'a str35 pub fn data(&self) -> &'a str {
36 &self.input[self.offset.get()..]
37 }
38
string(&self) -> Option<&'a str>39 pub fn string(&self) -> Option<&'a str> {
40 println!("string()");
41 match string(self.data()) {
42 Ok((i, s)) => {
43 self.offset(i);
44 println!("-> {}", s);
45 Some(s)
46 }
47 _ => None,
48 }
49 }
50
boolean(&self) -> Option<bool>51 pub fn boolean(&self) -> Option<bool> {
52 println!("boolean()");
53 match boolean(self.data()) {
54 Ok((i, o)) => {
55 self.offset(i);
56 println!("-> {}", o);
57 Some(o)
58 }
59 _ => None,
60 }
61 }
62
number(&self) -> Option<f64>63 pub fn number(&self) -> Option<f64> {
64 println!("number()");
65 match double::<_, ()>(self.data()) {
66 Ok((i, o)) => {
67 self.offset(i);
68 println!("-> {}", o);
69 Some(o)
70 }
71 _ => None,
72 }
73 }
74
array(&self) -> Option<impl Iterator<Item = JsonValue<'a, 'b>>>75 pub fn array(&self) -> Option<impl Iterator<Item = JsonValue<'a, 'b>>> {
76 println!("array()");
77
78 match tag::<_, _, ()>("[")(self.data()) {
79 Err(_) => None,
80 Ok((i, _)) => {
81 println!("[");
82 self.offset(i);
83 let mut first = true;
84 let mut done = false;
85 let mut previous = std::usize::MAX;
86
87 let v = self.clone();
88
89 Some(std::iter::from_fn(move || {
90 if done {
91 return None;
92 }
93
94 // if we ignored one of the items, skip over the value
95 if v.offset.get() == previous {
96 println!("skipping value");
97 match value(v.data()) {
98 Ok((i, _)) => {
99 v.offset(i);
100 }
101 Err(_) => {}
102 }
103 }
104
105 match tag::<_, _, ()>("]")(v.data()) {
106 Ok((i, _)) => {
107 println!("]");
108 v.offset(i);
109 done = true;
110 return None;
111 }
112 Err(_) => {}
113 };
114
115 if first {
116 first = false;
117 } else {
118 match tag::<_, _, ()>(",")(v.data()) {
119 Ok((i, _)) => {
120 println!(",");
121 v.offset(i);
122 }
123 Err(_) => {
124 done = true;
125 return None;
126 }
127 }
128 }
129
130 println!("-> {}", v.data());
131 previous = v.offset.get();
132 Some(v.clone())
133 }))
134 }
135 }
136 }
137
object(&self) -> Option<impl Iterator<Item = (&'a str, JsonValue<'a, 'b>)>>138 pub fn object(&self) -> Option<impl Iterator<Item = (&'a str, JsonValue<'a, 'b>)>> {
139 println!("object()");
140 match tag::<_, _, ()>("{")(self.data()) {
141 Err(_) => None,
142 Ok((i, _)) => {
143 self.offset(i);
144
145 println!("{{");
146
147 let mut first = true;
148 let mut done = false;
149 let mut previous = std::usize::MAX;
150
151 let v = self.clone();
152
153 Some(std::iter::from_fn(move || {
154 if done {
155 return None;
156 }
157
158 // if we ignored one of the items, skip over the value
159 if v.offset.get() == previous {
160 println!("skipping value");
161 match value(v.data()) {
162 Ok((i, _)) => {
163 v.offset(i);
164 }
165 Err(_) => {}
166 }
167 }
168
169 match tag::<_, _, ()>("}")(v.data()) {
170 Ok((i, _)) => {
171 println!("}}");
172 v.offset(i);
173 done = true;
174 return None;
175 }
176 Err(_) => {}
177 };
178
179 if first {
180 first = false;
181 } else {
182 match tag::<_, _, ()>(",")(v.data()) {
183 Ok((i, _)) => {
184 println!(",");
185 v.offset(i);
186 }
187 Err(_) => {
188 done = true;
189 return None;
190 }
191 }
192 }
193
194 match string(v.data()) {
195 Ok((i, key)) => {
196 v.offset(i);
197
198 match tag::<_, _, ()>(":")(v.data()) {
199 Err(_) => None,
200 Ok((i, _)) => {
201 v.offset(i);
202
203 previous = v.offset.get();
204
205 println!("-> {} => {}", key, v.data());
206 Some((key, v.clone()))
207 }
208 }
209 }
210 _ => None,
211 }
212 }))
213 }
214 }
215 }
216 }
217
sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E>218 fn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
219 let chars = " \t\r\n";
220
221 take_while(move |c| chars.contains(c))(i)
222 }
223
parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E>224 fn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
225 escaped(alphanumeric, '\\', one_of("\"n\\"))(i)
226 }
227
228 fn string<'a>(i: &'a str) -> IResult<&'a str, &'a str> {
229 context(
230 "string",
231 preceded(char('\"'), cut(terminated(parse_str, char('\"')))),
232 )(i)
233 }
234
235 fn boolean<'a>(input: &'a str) -> IResult<&'a str, bool> {
236 alt((map(tag("false"), |_| false), map(tag("true"), |_| true)))(input)
237 }
238
239 fn array<'a>(i: &'a str) -> IResult<&'a str, ()> {
240 context(
241 "array",
242 preceded(
243 char('['),
244 cut(terminated(
245 map(separated_list0(preceded(sp, char(',')), value), |_| ()),
246 preceded(sp, char(']')),
247 )),
248 ),
249 )(i)
250 }
251
252 fn key_value<'a>(i: &'a str) -> IResult<&'a str, (&'a str, ())> {
253 separated_pair(preceded(sp, string), cut(preceded(sp, char(':'))), value)(i)
254 }
255
256 fn hash<'a>(i: &'a str) -> IResult<&'a str, ()> {
257 context(
258 "map",
259 preceded(
260 char('{'),
261 cut(terminated(
262 map(separated_list0(preceded(sp, char(',')), key_value), |_| ()),
263 preceded(sp, char('}')),
264 )),
265 ),
266 )(i)
267 }
268
269 fn value<'a>(i: &'a str) -> IResult<&'a str, ()> {
270 preceded(
271 sp,
272 alt((
273 hash,
274 array,
275 map(string, |_| ()),
276 map(double, |_| ()),
277 map(boolean, |_| ()),
278 )),
279 )(i)
280 }
281
282 /// object(input) -> iterator over (key, JsonValue)
283 /// array(input) -> iterator over JsonValue
284 ///
285 /// JsonValue.string -> iterator over String (returns None after first successful call)
286 ///
287 /// object(input).filter(|(k, _)| k == "users").flatten(|(_, v)| v.object()).filter(|(k, _)| k == "city").flatten(|(_,v)| v.string())
288 fn main() {
289 /*let data = "{
290 \"users\": {
291 \"user1\" : { \"city\": \"Nantes\", \"country\": \"France\" },
292 \"user2\" : { \"city\": \"Bruxelles\", \"country\": \"Belgium\" },
293 \"user3\": { \"city\": \"Paris\", \"country\": \"France\", \"age\": 30 }
294 },
295 \"countries\": [\"France\", \"Belgium\"]
296 }";
297 */
298 let data = "{\"users\":{\"user1\":{\"city\":\"Nantes\",\"country\":\"France\"},\"user2\":{\"city\":\"Bruxelles\",\"country\":\"Belgium\"},\"user3\":{\"city\":\"Paris\",\"country\":\"France\",\"age\":30}},\"countries\":[\"France\",\"Belgium\"]}";
299
300 let offset = Cell::new(0);
301 {
302 let parser = JsonValue::new(data, &offset);
303
304 if let Some(o) = parser.object() {
305 let s: HashMap<&str, &str> = o
306 .filter(|(k, _)| *k == "users")
307 .filter_map(|(_, v)| v.object())
308 .flatten()
309 .filter_map(|(user, v)| v.object().map(|o| (user, o)))
310 .map(|(user, o)| {
311 o.filter(|(k, _)| *k == "city")
312 .filter_map(move |(_, v)| v.string().map(|s| (user, s)))
313 })
314 .flatten()
315 .collect();
316
317 println!("res = {:?}", s);
318 }
319 };
320 }
321