16855e09eSopenharmony_ci#[macro_use] 26855e09eSopenharmony_ciextern crate criterion; 36855e09eSopenharmony_ci 46855e09eSopenharmony_ci#[global_allocator] 56855e09eSopenharmony_cistatic ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; 66855e09eSopenharmony_ci 76855e09eSopenharmony_ciuse criterion::Criterion; 86855e09eSopenharmony_ciuse nom::{ 96855e09eSopenharmony_ci branch::alt, 106855e09eSopenharmony_ci bytes::complete::{tag, take}, 116855e09eSopenharmony_ci character::complete::{anychar, char, multispace0, none_of}, 126855e09eSopenharmony_ci combinator::{map, map_opt, map_res, value, verify}, 136855e09eSopenharmony_ci error::{ErrorKind, ParseError}, 146855e09eSopenharmony_ci multi::{fold_many0, separated_list0}, 156855e09eSopenharmony_ci number::complete::{double, recognize_float}, 166855e09eSopenharmony_ci sequence::{delimited, preceded, separated_pair}, 176855e09eSopenharmony_ci IResult, Parser, 186855e09eSopenharmony_ci}; 196855e09eSopenharmony_ci 206855e09eSopenharmony_ciuse std::collections::HashMap; 216855e09eSopenharmony_ci 226855e09eSopenharmony_ci#[derive(Debug, PartialEq, Clone)] 236855e09eSopenharmony_cipub enum JsonValue { 246855e09eSopenharmony_ci Null, 256855e09eSopenharmony_ci Bool(bool), 266855e09eSopenharmony_ci Str(String), 276855e09eSopenharmony_ci Num(f64), 286855e09eSopenharmony_ci Array(Vec<JsonValue>), 296855e09eSopenharmony_ci Object(HashMap<String, JsonValue>), 306855e09eSopenharmony_ci} 316855e09eSopenharmony_ci 326855e09eSopenharmony_cifn boolean(input: &str) -> IResult<&str, bool> { 336855e09eSopenharmony_ci alt((value(false, tag("false")), value(true, tag("true"))))(input) 346855e09eSopenharmony_ci} 356855e09eSopenharmony_ci 366855e09eSopenharmony_cifn u16_hex(input: &str) -> IResult<&str, u16> { 376855e09eSopenharmony_ci map_res(take(4usize), |s| u16::from_str_radix(s, 16))(input) 386855e09eSopenharmony_ci} 396855e09eSopenharmony_ci 406855e09eSopenharmony_cifn unicode_escape(input: &str) -> IResult<&str, char> { 416855e09eSopenharmony_ci map_opt( 426855e09eSopenharmony_ci alt(( 436855e09eSopenharmony_ci // Not a surrogate 446855e09eSopenharmony_ci map(verify(u16_hex, |cp| !(0xD800..0xE000).contains(cp)), |cp| { 456855e09eSopenharmony_ci cp as u32 466855e09eSopenharmony_ci }), 476855e09eSopenharmony_ci // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details 486855e09eSopenharmony_ci map( 496855e09eSopenharmony_ci verify( 506855e09eSopenharmony_ci separated_pair(u16_hex, tag("\\u"), u16_hex), 516855e09eSopenharmony_ci |(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low), 526855e09eSopenharmony_ci ), 536855e09eSopenharmony_ci |(high, low)| { 546855e09eSopenharmony_ci let high_ten = (high as u32) - 0xD800; 556855e09eSopenharmony_ci let low_ten = (low as u32) - 0xDC00; 566855e09eSopenharmony_ci (high_ten << 10) + low_ten + 0x10000 576855e09eSopenharmony_ci }, 586855e09eSopenharmony_ci ), 596855e09eSopenharmony_ci )), 606855e09eSopenharmony_ci // Could probably be replaced with .unwrap() or _unchecked due to the verify checks 616855e09eSopenharmony_ci std::char::from_u32, 626855e09eSopenharmony_ci )(input) 636855e09eSopenharmony_ci} 646855e09eSopenharmony_ci 656855e09eSopenharmony_cifn character(input: &str) -> IResult<&str, char> { 666855e09eSopenharmony_ci let (input, c) = none_of("\"")(input)?; 676855e09eSopenharmony_ci if c == '\\' { 686855e09eSopenharmony_ci alt(( 696855e09eSopenharmony_ci map_res(anychar, |c| { 706855e09eSopenharmony_ci Ok(match c { 716855e09eSopenharmony_ci '"' | '\\' | '/' => c, 726855e09eSopenharmony_ci 'b' => '\x08', 736855e09eSopenharmony_ci 'f' => '\x0C', 746855e09eSopenharmony_ci 'n' => '\n', 756855e09eSopenharmony_ci 'r' => '\r', 766855e09eSopenharmony_ci 't' => '\t', 776855e09eSopenharmony_ci _ => return Err(()), 786855e09eSopenharmony_ci }) 796855e09eSopenharmony_ci }), 806855e09eSopenharmony_ci preceded(char('u'), unicode_escape), 816855e09eSopenharmony_ci ))(input) 826855e09eSopenharmony_ci } else { 836855e09eSopenharmony_ci Ok((input, c)) 846855e09eSopenharmony_ci } 856855e09eSopenharmony_ci} 866855e09eSopenharmony_ci 876855e09eSopenharmony_cifn string(input: &str) -> IResult<&str, String> { 886855e09eSopenharmony_ci delimited( 896855e09eSopenharmony_ci char('"'), 906855e09eSopenharmony_ci fold_many0(character, String::new, |mut string, c| { 916855e09eSopenharmony_ci string.push(c); 926855e09eSopenharmony_ci string 936855e09eSopenharmony_ci }), 946855e09eSopenharmony_ci char('"'), 956855e09eSopenharmony_ci )(input) 966855e09eSopenharmony_ci} 976855e09eSopenharmony_ci 986855e09eSopenharmony_cifn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> { 996855e09eSopenharmony_ci delimited(multispace0, f, multispace0) 1006855e09eSopenharmony_ci} 1016855e09eSopenharmony_ci 1026855e09eSopenharmony_cifn array(input: &str) -> IResult<&str, Vec<JsonValue>> { 1036855e09eSopenharmony_ci delimited( 1046855e09eSopenharmony_ci char('['), 1056855e09eSopenharmony_ci ws(separated_list0(ws(char(',')), json_value)), 1066855e09eSopenharmony_ci char(']'), 1076855e09eSopenharmony_ci )(input) 1086855e09eSopenharmony_ci} 1096855e09eSopenharmony_ci 1106855e09eSopenharmony_cifn object(input: &str) -> IResult<&str, HashMap<String, JsonValue>> { 1116855e09eSopenharmony_ci map( 1126855e09eSopenharmony_ci delimited( 1136855e09eSopenharmony_ci char('{'), 1146855e09eSopenharmony_ci ws(separated_list0( 1156855e09eSopenharmony_ci ws(char(',')), 1166855e09eSopenharmony_ci separated_pair(string, ws(char(':')), json_value), 1176855e09eSopenharmony_ci )), 1186855e09eSopenharmony_ci char('}'), 1196855e09eSopenharmony_ci ), 1206855e09eSopenharmony_ci |key_values| key_values.into_iter().collect(), 1216855e09eSopenharmony_ci )(input) 1226855e09eSopenharmony_ci} 1236855e09eSopenharmony_ci 1246855e09eSopenharmony_cifn json_value(input: &str) -> IResult<&str, JsonValue> { 1256855e09eSopenharmony_ci use JsonValue::*; 1266855e09eSopenharmony_ci 1276855e09eSopenharmony_ci alt(( 1286855e09eSopenharmony_ci value(Null, tag("null")), 1296855e09eSopenharmony_ci map(boolean, Bool), 1306855e09eSopenharmony_ci map(string, Str), 1316855e09eSopenharmony_ci map(double, Num), 1326855e09eSopenharmony_ci map(array, Array), 1336855e09eSopenharmony_ci map(object, Object), 1346855e09eSopenharmony_ci ))(input) 1356855e09eSopenharmony_ci} 1366855e09eSopenharmony_ci 1376855e09eSopenharmony_cifn json(input: &str) -> IResult<&str, JsonValue> { 1386855e09eSopenharmony_ci ws(json_value).parse(input) 1396855e09eSopenharmony_ci} 1406855e09eSopenharmony_ci 1416855e09eSopenharmony_cifn json_bench(c: &mut Criterion) { 1426855e09eSopenharmony_ci let data = " { \"a\"\t: 42, 1436855e09eSopenharmony_ci \"b\": [ \"x\", \"y\", 12 ,\"\\u2014\", \"\\uD83D\\uDE10\"] , 1446855e09eSopenharmony_ci \"c\": { \"hello\" : \"world\" 1456855e09eSopenharmony_ci } 1466855e09eSopenharmony_ci } "; 1476855e09eSopenharmony_ci 1486855e09eSopenharmony_ci // println!("data:\n{:?}", json(data)); 1496855e09eSopenharmony_ci c.bench_function("json", |b| { 1506855e09eSopenharmony_ci b.iter(|| json(data).unwrap()); 1516855e09eSopenharmony_ci }); 1526855e09eSopenharmony_ci} 1536855e09eSopenharmony_ci 1546855e09eSopenharmony_cifn recognize_float_bytes(c: &mut Criterion) { 1556855e09eSopenharmony_ci println!( 1566855e09eSopenharmony_ci "recognize_float_bytes result: {:?}", 1576855e09eSopenharmony_ci recognize_float::<_, (_, ErrorKind)>(&b"-1.234E-12"[..]) 1586855e09eSopenharmony_ci ); 1596855e09eSopenharmony_ci c.bench_function("recognize float bytes", |b| { 1606855e09eSopenharmony_ci b.iter(|| recognize_float::<_, (_, ErrorKind)>(&b"-1.234E-12"[..])); 1616855e09eSopenharmony_ci }); 1626855e09eSopenharmony_ci} 1636855e09eSopenharmony_ci 1646855e09eSopenharmony_cifn recognize_float_str(c: &mut Criterion) { 1656855e09eSopenharmony_ci println!( 1666855e09eSopenharmony_ci "recognize_float_str result: {:?}", 1676855e09eSopenharmony_ci recognize_float::<_, (_, ErrorKind)>("-1.234E-12") 1686855e09eSopenharmony_ci ); 1696855e09eSopenharmony_ci c.bench_function("recognize float str", |b| { 1706855e09eSopenharmony_ci b.iter(|| recognize_float::<_, (_, ErrorKind)>("-1.234E-12")); 1716855e09eSopenharmony_ci }); 1726855e09eSopenharmony_ci} 1736855e09eSopenharmony_ci 1746855e09eSopenharmony_cifn float_bytes(c: &mut Criterion) { 1756855e09eSopenharmony_ci println!( 1766855e09eSopenharmony_ci "float_bytes result: {:?}", 1776855e09eSopenharmony_ci double::<_, (_, ErrorKind)>(&b"-1.234E-12"[..]) 1786855e09eSopenharmony_ci ); 1796855e09eSopenharmony_ci c.bench_function("float bytes", |b| { 1806855e09eSopenharmony_ci b.iter(|| double::<_, (_, ErrorKind)>(&b"-1.234E-12"[..])); 1816855e09eSopenharmony_ci }); 1826855e09eSopenharmony_ci} 1836855e09eSopenharmony_ci 1846855e09eSopenharmony_cifn float_str(c: &mut Criterion) { 1856855e09eSopenharmony_ci println!( 1866855e09eSopenharmony_ci "float_str result: {:?}", 1876855e09eSopenharmony_ci double::<_, (_, ErrorKind)>("-1.234E-12") 1886855e09eSopenharmony_ci ); 1896855e09eSopenharmony_ci c.bench_function("float str", |b| { 1906855e09eSopenharmony_ci b.iter(|| double::<_, (_, ErrorKind)>("-1.234E-12")); 1916855e09eSopenharmony_ci }); 1926855e09eSopenharmony_ci} 1936855e09eSopenharmony_ci 1946855e09eSopenharmony_ciuse nom::Err; 1956855e09eSopenharmony_ciuse nom::ParseTo; 1966855e09eSopenharmony_cifn std_float(input: &[u8]) -> IResult<&[u8], f64, (&[u8], ErrorKind)> { 1976855e09eSopenharmony_ci match recognize_float(input) { 1986855e09eSopenharmony_ci Err(e) => Err(e), 1996855e09eSopenharmony_ci Ok((i, s)) => match s.parse_to() { 2006855e09eSopenharmony_ci Some(n) => Ok((i, n)), 2016855e09eSopenharmony_ci None => Err(Err::Error((i, ErrorKind::Float))), 2026855e09eSopenharmony_ci }, 2036855e09eSopenharmony_ci } 2046855e09eSopenharmony_ci} 2056855e09eSopenharmony_ci 2066855e09eSopenharmony_cifn std_float_bytes(c: &mut Criterion) { 2076855e09eSopenharmony_ci println!( 2086855e09eSopenharmony_ci "std_float_bytes result: {:?}", 2096855e09eSopenharmony_ci std_float(&b"-1.234E-12"[..]) 2106855e09eSopenharmony_ci ); 2116855e09eSopenharmony_ci c.bench_function("std_float bytes", |b| { 2126855e09eSopenharmony_ci b.iter(|| std_float(&b"-1.234E-12"[..])); 2136855e09eSopenharmony_ci }); 2146855e09eSopenharmony_ci} 2156855e09eSopenharmony_ci 2166855e09eSopenharmony_cicriterion_group!( 2176855e09eSopenharmony_ci benches, 2186855e09eSopenharmony_ci json_bench, 2196855e09eSopenharmony_ci recognize_float_bytes, 2206855e09eSopenharmony_ci recognize_float_str, 2216855e09eSopenharmony_ci float_bytes, 2226855e09eSopenharmony_ci std_float_bytes, 2236855e09eSopenharmony_ci float_str 2246855e09eSopenharmony_ci); 2256855e09eSopenharmony_cicriterion_main!(benches); 226