Skip to content

Commit

Permalink
Merge pull request #94 from wackbyte/zero-copy-add-nom-bench
Browse files Browse the repository at this point in the history
[zero-copy] Add nom benchmark
  • Loading branch information
zesterer authored Feb 28, 2022
2 parents b01d60f + 6c70edc commit 1ab8b05
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ regex = { version = "1.5", optional = true }
[dev-dependencies]
ariadne = "0.1.2"
pom = "3.0"
nom = "7.1"
serde_json = { version = "1.0", features = ["preserve_order"] }
105 changes: 105 additions & 0 deletions benches/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ fn pom(b: &mut Bencher) {
b.iter(|| black_box(json.parse(JSON).unwrap()));
}

#[bench]
fn nom(b: &mut Bencher) {
b.iter(|| black_box(nom::json(JSON).unwrap()));
}

mod chumsky_zero_copy {
use chumsky::input::*;

Expand Down Expand Up @@ -292,3 +297,103 @@ mod pom {
space() * value() - end()
}
}

mod nom {
use nom::{
branch::alt,
bytes::complete::{escaped, tag, take_while},
character::complete::{char, digit0, digit1, none_of, one_of},
combinator::{cut, map, opt, recognize, value as to},
error::ParseError,
multi::separated_list0,
sequence::{preceded, separated_pair, terminated, tuple},
IResult,
};

use super::JsonZero;
use std::str;

fn space<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> {
take_while(|c| b" \t\r\n".contains(&c))(i)
}

fn number<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], f64, E> {
map(
recognize(tuple((
opt(char('-')),
alt((
to((), tuple((one_of("123456789"), digit0))),
to((), char('0')),
)),
opt(tuple((char('.'), digit1))),
opt(tuple((one_of("eE"), opt(one_of("+-")), cut(digit1)))),
))),
|bytes| str::from_utf8(bytes).unwrap().parse::<f64>().unwrap(),
)(i)
}

fn string<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> {
preceded(
char('"'),
cut(terminated(
escaped(none_of("\\\""), '\\', one_of("\\/\"bfnrt")),
char('"'),
)),
)(i)
}

fn array<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], Vec<JsonZero>, E> {
preceded(
char('['),
cut(terminated(
separated_list0(preceded(space, char(',')), value),
preceded(space, char(']')),
)),
)(i)
}

fn member<'a, E: ParseError<&'a [u8]>>(
i: &'a [u8],
) -> IResult<&'a [u8], (&'a [u8], JsonZero), E> {
separated_pair(
preceded(space, string),
cut(preceded(space, char(':'))),
value,
)(i)
}

fn object<'a, E: ParseError<&'a [u8]>>(
i: &'a [u8],
) -> IResult<&'a [u8], Vec<(&'a [u8], JsonZero)>, E> {
preceded(
char('{'),
cut(terminated(
separated_list0(preceded(space, char(',')), member),
preceded(space, char('}')),
)),
)(i)
}

fn value<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], JsonZero, E> {
preceded(
space,
alt((
to(JsonZero::Null, tag("null")),
to(JsonZero::Bool(true), tag("true")),
to(JsonZero::Bool(false), tag("false")),
map(number, JsonZero::Num),
map(string, JsonZero::Str),
map(array, JsonZero::Array),
map(object, JsonZero::Object),
)),
)(i)
}

fn root<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], JsonZero, E> {
terminated(value, space)(i)
}

pub fn json<'a>(i: &'a [u8]) -> IResult<&'a [u8], JsonZero, (&'a [u8], nom::error::ErrorKind)> {
root(i)
}
}

0 comments on commit 1ab8b05

Please sign in to comment.