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