16855e09eSopenharmony_ci#![cfg(feature = "alloc")] 26855e09eSopenharmony_ci 36855e09eSopenharmony_ciuse nom::{ 46855e09eSopenharmony_ci branch::alt, 56855e09eSopenharmony_ci bytes::complete::{escaped, tag, take_while}, 66855e09eSopenharmony_ci character::complete::{alphanumeric1 as alphanumeric, char, one_of}, 76855e09eSopenharmony_ci combinator::{cut, map}, 86855e09eSopenharmony_ci error::{context, ParseError}, 96855e09eSopenharmony_ci multi::separated_list0, 106855e09eSopenharmony_ci number::complete::double, 116855e09eSopenharmony_ci sequence::{preceded, separated_pair, terminated}, 126855e09eSopenharmony_ci IResult, 136855e09eSopenharmony_ci}; 146855e09eSopenharmony_ciuse std::collections::HashMap; 156855e09eSopenharmony_ci 166855e09eSopenharmony_ciuse std::cell::Cell; 176855e09eSopenharmony_ciuse std::str; 186855e09eSopenharmony_ci 196855e09eSopenharmony_ci#[derive(Clone, Debug)] 206855e09eSopenharmony_cipub struct JsonValue<'a, 'b> { 216855e09eSopenharmony_ci input: &'a str, 226855e09eSopenharmony_ci pub offset: &'b Cell<usize>, 236855e09eSopenharmony_ci} 246855e09eSopenharmony_ci 256855e09eSopenharmony_ciimpl<'a, 'b: 'a> JsonValue<'a, 'b> { 266855e09eSopenharmony_ci pub fn new(input: &'a str, offset: &'b Cell<usize>) -> JsonValue<'a, 'b> { 276855e09eSopenharmony_ci JsonValue { input, offset } 286855e09eSopenharmony_ci } 296855e09eSopenharmony_ci 306855e09eSopenharmony_ci pub fn offset(&self, input: &'a str) { 316855e09eSopenharmony_ci let offset = input.as_ptr() as usize - self.input.as_ptr() as usize; 326855e09eSopenharmony_ci self.offset.set(offset); 336855e09eSopenharmony_ci } 346855e09eSopenharmony_ci 356855e09eSopenharmony_ci pub fn data(&self) -> &'a str { 366855e09eSopenharmony_ci &self.input[self.offset.get()..] 376855e09eSopenharmony_ci } 386855e09eSopenharmony_ci 396855e09eSopenharmony_ci pub fn string(&self) -> Option<&'a str> { 406855e09eSopenharmony_ci println!("string()"); 416855e09eSopenharmony_ci match string(self.data()) { 426855e09eSopenharmony_ci Ok((i, s)) => { 436855e09eSopenharmony_ci self.offset(i); 446855e09eSopenharmony_ci println!("-> {}", s); 456855e09eSopenharmony_ci Some(s) 466855e09eSopenharmony_ci } 476855e09eSopenharmony_ci _ => None, 486855e09eSopenharmony_ci } 496855e09eSopenharmony_ci } 506855e09eSopenharmony_ci 516855e09eSopenharmony_ci pub fn boolean(&self) -> Option<bool> { 526855e09eSopenharmony_ci println!("boolean()"); 536855e09eSopenharmony_ci match boolean(self.data()) { 546855e09eSopenharmony_ci Ok((i, o)) => { 556855e09eSopenharmony_ci self.offset(i); 566855e09eSopenharmony_ci println!("-> {}", o); 576855e09eSopenharmony_ci Some(o) 586855e09eSopenharmony_ci } 596855e09eSopenharmony_ci _ => None, 606855e09eSopenharmony_ci } 616855e09eSopenharmony_ci } 626855e09eSopenharmony_ci 636855e09eSopenharmony_ci pub fn number(&self) -> Option<f64> { 646855e09eSopenharmony_ci println!("number()"); 656855e09eSopenharmony_ci match double::<_, ()>(self.data()) { 666855e09eSopenharmony_ci Ok((i, o)) => { 676855e09eSopenharmony_ci self.offset(i); 686855e09eSopenharmony_ci println!("-> {}", o); 696855e09eSopenharmony_ci Some(o) 706855e09eSopenharmony_ci } 716855e09eSopenharmony_ci _ => None, 726855e09eSopenharmony_ci } 736855e09eSopenharmony_ci } 746855e09eSopenharmony_ci 756855e09eSopenharmony_ci pub fn array(&self) -> Option<impl Iterator<Item = JsonValue<'a, 'b>>> { 766855e09eSopenharmony_ci println!("array()"); 776855e09eSopenharmony_ci 786855e09eSopenharmony_ci match tag::<_, _, ()>("[")(self.data()) { 796855e09eSopenharmony_ci Err(_) => None, 806855e09eSopenharmony_ci Ok((i, _)) => { 816855e09eSopenharmony_ci println!("["); 826855e09eSopenharmony_ci self.offset(i); 836855e09eSopenharmony_ci let mut first = true; 846855e09eSopenharmony_ci let mut done = false; 856855e09eSopenharmony_ci let mut previous = std::usize::MAX; 866855e09eSopenharmony_ci 876855e09eSopenharmony_ci let v = self.clone(); 886855e09eSopenharmony_ci 896855e09eSopenharmony_ci Some(std::iter::from_fn(move || { 906855e09eSopenharmony_ci if done { 916855e09eSopenharmony_ci return None; 926855e09eSopenharmony_ci } 936855e09eSopenharmony_ci 946855e09eSopenharmony_ci // if we ignored one of the items, skip over the value 956855e09eSopenharmony_ci if v.offset.get() == previous { 966855e09eSopenharmony_ci println!("skipping value"); 976855e09eSopenharmony_ci match value(v.data()) { 986855e09eSopenharmony_ci Ok((i, _)) => { 996855e09eSopenharmony_ci v.offset(i); 1006855e09eSopenharmony_ci } 1016855e09eSopenharmony_ci Err(_) => {} 1026855e09eSopenharmony_ci } 1036855e09eSopenharmony_ci } 1046855e09eSopenharmony_ci 1056855e09eSopenharmony_ci match tag::<_, _, ()>("]")(v.data()) { 1066855e09eSopenharmony_ci Ok((i, _)) => { 1076855e09eSopenharmony_ci println!("]"); 1086855e09eSopenharmony_ci v.offset(i); 1096855e09eSopenharmony_ci done = true; 1106855e09eSopenharmony_ci return None; 1116855e09eSopenharmony_ci } 1126855e09eSopenharmony_ci Err(_) => {} 1136855e09eSopenharmony_ci }; 1146855e09eSopenharmony_ci 1156855e09eSopenharmony_ci if first { 1166855e09eSopenharmony_ci first = false; 1176855e09eSopenharmony_ci } else { 1186855e09eSopenharmony_ci match tag::<_, _, ()>(",")(v.data()) { 1196855e09eSopenharmony_ci Ok((i, _)) => { 1206855e09eSopenharmony_ci println!(","); 1216855e09eSopenharmony_ci v.offset(i); 1226855e09eSopenharmony_ci } 1236855e09eSopenharmony_ci Err(_) => { 1246855e09eSopenharmony_ci done = true; 1256855e09eSopenharmony_ci return None; 1266855e09eSopenharmony_ci } 1276855e09eSopenharmony_ci } 1286855e09eSopenharmony_ci } 1296855e09eSopenharmony_ci 1306855e09eSopenharmony_ci println!("-> {}", v.data()); 1316855e09eSopenharmony_ci previous = v.offset.get(); 1326855e09eSopenharmony_ci Some(v.clone()) 1336855e09eSopenharmony_ci })) 1346855e09eSopenharmony_ci } 1356855e09eSopenharmony_ci } 1366855e09eSopenharmony_ci } 1376855e09eSopenharmony_ci 1386855e09eSopenharmony_ci pub fn object(&self) -> Option<impl Iterator<Item = (&'a str, JsonValue<'a, 'b>)>> { 1396855e09eSopenharmony_ci println!("object()"); 1406855e09eSopenharmony_ci match tag::<_, _, ()>("{")(self.data()) { 1416855e09eSopenharmony_ci Err(_) => None, 1426855e09eSopenharmony_ci Ok((i, _)) => { 1436855e09eSopenharmony_ci self.offset(i); 1446855e09eSopenharmony_ci 1456855e09eSopenharmony_ci println!("{{"); 1466855e09eSopenharmony_ci 1476855e09eSopenharmony_ci let mut first = true; 1486855e09eSopenharmony_ci let mut done = false; 1496855e09eSopenharmony_ci let mut previous = std::usize::MAX; 1506855e09eSopenharmony_ci 1516855e09eSopenharmony_ci let v = self.clone(); 1526855e09eSopenharmony_ci 1536855e09eSopenharmony_ci Some(std::iter::from_fn(move || { 1546855e09eSopenharmony_ci if done { 1556855e09eSopenharmony_ci return None; 1566855e09eSopenharmony_ci } 1576855e09eSopenharmony_ci 1586855e09eSopenharmony_ci // if we ignored one of the items, skip over the value 1596855e09eSopenharmony_ci if v.offset.get() == previous { 1606855e09eSopenharmony_ci println!("skipping value"); 1616855e09eSopenharmony_ci match value(v.data()) { 1626855e09eSopenharmony_ci Ok((i, _)) => { 1636855e09eSopenharmony_ci v.offset(i); 1646855e09eSopenharmony_ci } 1656855e09eSopenharmony_ci Err(_) => {} 1666855e09eSopenharmony_ci } 1676855e09eSopenharmony_ci } 1686855e09eSopenharmony_ci 1696855e09eSopenharmony_ci match tag::<_, _, ()>("}")(v.data()) { 1706855e09eSopenharmony_ci Ok((i, _)) => { 1716855e09eSopenharmony_ci println!("}}"); 1726855e09eSopenharmony_ci v.offset(i); 1736855e09eSopenharmony_ci done = true; 1746855e09eSopenharmony_ci return None; 1756855e09eSopenharmony_ci } 1766855e09eSopenharmony_ci Err(_) => {} 1776855e09eSopenharmony_ci }; 1786855e09eSopenharmony_ci 1796855e09eSopenharmony_ci if first { 1806855e09eSopenharmony_ci first = false; 1816855e09eSopenharmony_ci } else { 1826855e09eSopenharmony_ci match tag::<_, _, ()>(",")(v.data()) { 1836855e09eSopenharmony_ci Ok((i, _)) => { 1846855e09eSopenharmony_ci println!(","); 1856855e09eSopenharmony_ci v.offset(i); 1866855e09eSopenharmony_ci } 1876855e09eSopenharmony_ci Err(_) => { 1886855e09eSopenharmony_ci done = true; 1896855e09eSopenharmony_ci return None; 1906855e09eSopenharmony_ci } 1916855e09eSopenharmony_ci } 1926855e09eSopenharmony_ci } 1936855e09eSopenharmony_ci 1946855e09eSopenharmony_ci match string(v.data()) { 1956855e09eSopenharmony_ci Ok((i, key)) => { 1966855e09eSopenharmony_ci v.offset(i); 1976855e09eSopenharmony_ci 1986855e09eSopenharmony_ci match tag::<_, _, ()>(":")(v.data()) { 1996855e09eSopenharmony_ci Err(_) => None, 2006855e09eSopenharmony_ci Ok((i, _)) => { 2016855e09eSopenharmony_ci v.offset(i); 2026855e09eSopenharmony_ci 2036855e09eSopenharmony_ci previous = v.offset.get(); 2046855e09eSopenharmony_ci 2056855e09eSopenharmony_ci println!("-> {} => {}", key, v.data()); 2066855e09eSopenharmony_ci Some((key, v.clone())) 2076855e09eSopenharmony_ci } 2086855e09eSopenharmony_ci } 2096855e09eSopenharmony_ci } 2106855e09eSopenharmony_ci _ => None, 2116855e09eSopenharmony_ci } 2126855e09eSopenharmony_ci })) 2136855e09eSopenharmony_ci } 2146855e09eSopenharmony_ci } 2156855e09eSopenharmony_ci } 2166855e09eSopenharmony_ci} 2176855e09eSopenharmony_ci 2186855e09eSopenharmony_cifn sp<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { 2196855e09eSopenharmony_ci let chars = " \t\r\n"; 2206855e09eSopenharmony_ci 2216855e09eSopenharmony_ci take_while(move |c| chars.contains(c))(i) 2226855e09eSopenharmony_ci} 2236855e09eSopenharmony_ci 2246855e09eSopenharmony_cifn parse_str<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> { 2256855e09eSopenharmony_ci escaped(alphanumeric, '\\', one_of("\"n\\"))(i) 2266855e09eSopenharmony_ci} 2276855e09eSopenharmony_ci 2286855e09eSopenharmony_cifn string<'a>(i: &'a str) -> IResult<&'a str, &'a str> { 2296855e09eSopenharmony_ci context( 2306855e09eSopenharmony_ci "string", 2316855e09eSopenharmony_ci preceded(char('\"'), cut(terminated(parse_str, char('\"')))), 2326855e09eSopenharmony_ci )(i) 2336855e09eSopenharmony_ci} 2346855e09eSopenharmony_ci 2356855e09eSopenharmony_cifn boolean<'a>(input: &'a str) -> IResult<&'a str, bool> { 2366855e09eSopenharmony_ci alt((map(tag("false"), |_| false), map(tag("true"), |_| true)))(input) 2376855e09eSopenharmony_ci} 2386855e09eSopenharmony_ci 2396855e09eSopenharmony_cifn array<'a>(i: &'a str) -> IResult<&'a str, ()> { 2406855e09eSopenharmony_ci context( 2416855e09eSopenharmony_ci "array", 2426855e09eSopenharmony_ci preceded( 2436855e09eSopenharmony_ci char('['), 2446855e09eSopenharmony_ci cut(terminated( 2456855e09eSopenharmony_ci map(separated_list0(preceded(sp, char(',')), value), |_| ()), 2466855e09eSopenharmony_ci preceded(sp, char(']')), 2476855e09eSopenharmony_ci )), 2486855e09eSopenharmony_ci ), 2496855e09eSopenharmony_ci )(i) 2506855e09eSopenharmony_ci} 2516855e09eSopenharmony_ci 2526855e09eSopenharmony_cifn key_value<'a>(i: &'a str) -> IResult<&'a str, (&'a str, ())> { 2536855e09eSopenharmony_ci separated_pair(preceded(sp, string), cut(preceded(sp, char(':'))), value)(i) 2546855e09eSopenharmony_ci} 2556855e09eSopenharmony_ci 2566855e09eSopenharmony_cifn hash<'a>(i: &'a str) -> IResult<&'a str, ()> { 2576855e09eSopenharmony_ci context( 2586855e09eSopenharmony_ci "map", 2596855e09eSopenharmony_ci preceded( 2606855e09eSopenharmony_ci char('{'), 2616855e09eSopenharmony_ci cut(terminated( 2626855e09eSopenharmony_ci map(separated_list0(preceded(sp, char(',')), key_value), |_| ()), 2636855e09eSopenharmony_ci preceded(sp, char('}')), 2646855e09eSopenharmony_ci )), 2656855e09eSopenharmony_ci ), 2666855e09eSopenharmony_ci )(i) 2676855e09eSopenharmony_ci} 2686855e09eSopenharmony_ci 2696855e09eSopenharmony_cifn value<'a>(i: &'a str) -> IResult<&'a str, ()> { 2706855e09eSopenharmony_ci preceded( 2716855e09eSopenharmony_ci sp, 2726855e09eSopenharmony_ci alt(( 2736855e09eSopenharmony_ci hash, 2746855e09eSopenharmony_ci array, 2756855e09eSopenharmony_ci map(string, |_| ()), 2766855e09eSopenharmony_ci map(double, |_| ()), 2776855e09eSopenharmony_ci map(boolean, |_| ()), 2786855e09eSopenharmony_ci )), 2796855e09eSopenharmony_ci )(i) 2806855e09eSopenharmony_ci} 2816855e09eSopenharmony_ci 2826855e09eSopenharmony_ci/// object(input) -> iterator over (key, JsonValue) 2836855e09eSopenharmony_ci/// array(input) -> iterator over JsonValue 2846855e09eSopenharmony_ci/// 2856855e09eSopenharmony_ci/// JsonValue.string -> iterator over String (returns None after first successful call) 2866855e09eSopenharmony_ci/// 2876855e09eSopenharmony_ci/// object(input).filter(|(k, _)| k == "users").flatten(|(_, v)| v.object()).filter(|(k, _)| k == "city").flatten(|(_,v)| v.string()) 2886855e09eSopenharmony_cifn main() { 2896855e09eSopenharmony_ci /*let data = "{ 2906855e09eSopenharmony_ci \"users\": { 2916855e09eSopenharmony_ci \"user1\" : { \"city\": \"Nantes\", \"country\": \"France\" }, 2926855e09eSopenharmony_ci \"user2\" : { \"city\": \"Bruxelles\", \"country\": \"Belgium\" }, 2936855e09eSopenharmony_ci \"user3\": { \"city\": \"Paris\", \"country\": \"France\", \"age\": 30 } 2946855e09eSopenharmony_ci }, 2956855e09eSopenharmony_ci \"countries\": [\"France\", \"Belgium\"] 2966855e09eSopenharmony_ci }"; 2976855e09eSopenharmony_ci */ 2986855e09eSopenharmony_ci let data = "{\"users\":{\"user1\":{\"city\":\"Nantes\",\"country\":\"France\"},\"user2\":{\"city\":\"Bruxelles\",\"country\":\"Belgium\"},\"user3\":{\"city\":\"Paris\",\"country\":\"France\",\"age\":30}},\"countries\":[\"France\",\"Belgium\"]}"; 2996855e09eSopenharmony_ci 3006855e09eSopenharmony_ci let offset = Cell::new(0); 3016855e09eSopenharmony_ci { 3026855e09eSopenharmony_ci let parser = JsonValue::new(data, &offset); 3036855e09eSopenharmony_ci 3046855e09eSopenharmony_ci if let Some(o) = parser.object() { 3056855e09eSopenharmony_ci let s: HashMap<&str, &str> = o 3066855e09eSopenharmony_ci .filter(|(k, _)| *k == "users") 3076855e09eSopenharmony_ci .filter_map(|(_, v)| v.object()) 3086855e09eSopenharmony_ci .flatten() 3096855e09eSopenharmony_ci .filter_map(|(user, v)| v.object().map(|o| (user, o))) 3106855e09eSopenharmony_ci .map(|(user, o)| { 3116855e09eSopenharmony_ci o.filter(|(k, _)| *k == "city") 3126855e09eSopenharmony_ci .filter_map(move |(_, v)| v.string().map(|s| (user, s))) 3136855e09eSopenharmony_ci }) 3146855e09eSopenharmony_ci .flatten() 3156855e09eSopenharmony_ci .collect(); 3166855e09eSopenharmony_ci 3176855e09eSopenharmony_ci println!("res = {:?}", s); 3186855e09eSopenharmony_ci } 3196855e09eSopenharmony_ci }; 3206855e09eSopenharmony_ci} 321