• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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