1#![cfg(feature = "alloc")] 2 3use 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}; 14use std::collections::HashMap; 15 16use std::cell::Cell; 17use std::str; 18 19#[derive(Clone, Debug)] 20pub struct JsonValue<'a, 'b> { 21 input: &'a str, 22 pub offset: &'b Cell<usize>, 23} 24 25impl<'a, 'b: 'a> JsonValue<'a, 'b> { 26 pub fn new(input: &'a str, offset: &'b Cell<usize>) -> JsonValue<'a, 'b> { 27 JsonValue { input, offset } 28 } 29 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 35 pub fn data(&self) -> &'a str { 36 &self.input[self.offset.get()..] 37 } 38 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 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 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 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 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 218fn 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 224fn 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 228fn 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 235fn boolean<'a>(input: &'a str) -> IResult<&'a str, bool> { 236 alt((map(tag("false"), |_| false), map(tag("true"), |_| true)))(input) 237} 238 239fn 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 252fn 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 256fn 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 269fn 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()) 288fn 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