Skip to content

Commit

Permalink
remove usage of CompleteByteSlice and CompleteStr
Browse files Browse the repository at this point in the history
since we now have specialized versions of a lot of parsers for streaming
or complete input cases, we can remove the awkward types CompleteByteSlice
and CompleteStr, along with uses of the AtEof trait that were present in
most combinators.
This change simplifies the code, and shows (especially in the arithmetic
expressions parser tests) that the new function based solution can
perform the same work as macros while simplifying the code on complete
input
  • Loading branch information
Geal committed Apr 17, 2019
1 parent f2db6e0 commit d85878e
Show file tree
Hide file tree
Showing 27 changed files with 515 additions and 1,913 deletions.
6 changes: 0 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ required-features = ["alloc"]
[[test]]
name = "blockbuf-arithmetic"

[[test]]
name = "complete_arithmetic"

[[test]]
name = "complete_float"

[[test]]
name = "css"

Expand Down
107 changes: 45 additions & 62 deletions benches/ini_complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

use criterion::*;
use nom::character::complete::{alphanumeric, multispace, space};
use nom::types::CompleteByteSlice;

use std::str;
use std::collections::HashMap;

named!(category<CompleteByteSlice, &str>, map_res!(
named!(category<&[u8], &str>, map_res!(
delimited!(
char!('['),
take_while!(call!(|c| c != b']')),
Expand All @@ -23,11 +22,11 @@ named!(category<CompleteByteSlice, &str>, map_res!(
complete_byte_slice_to_str
));

fn complete_byte_slice_to_str<'a>(s: CompleteByteSlice<'a>) -> Result<&'a str, str::Utf8Error> {
str::from_utf8(s.0)
fn complete_byte_slice_to_str<'a>(s: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
str::from_utf8(s)
}

named!(key_value <CompleteByteSlice,(&str,&str)>,
named!(key_value <&[u8],(&str,&str)>,
do_parse!(
key: map_res!(alphanumeric, complete_byte_slice_to_str)
>> opt!(space)
Expand All @@ -42,14 +41,14 @@ named!(key_value <CompleteByteSlice,(&str,&str)>,
)
);

named!(keys_and_values<CompleteByteSlice, HashMap<&str, &str> >,
named!(keys_and_values<&[u8], HashMap<&str, &str> >,
map!(
many0!(terminated!(key_value, opt!(multispace))),
|vec: Vec<_>| vec.into_iter().collect()
)
);

named!(category_and_keys<CompleteByteSlice,(&str,HashMap<&str,&str>)>,
named!(category_and_keys<&[u8],(&str,HashMap<&str,&str>)>,
do_parse!(
category: category >>
opt!(multispace) >>
Expand All @@ -58,7 +57,7 @@ named!(category_and_keys<CompleteByteSlice,(&str,HashMap<&str,&str>)>,
)
);

named!(categories<CompleteByteSlice, HashMap<&str, HashMap<&str,&str> > >,
named!(categories<&[u8], HashMap<&str, HashMap<&str,&str> > >,
map!(
many0!(
separated_pair!(
Expand All @@ -76,22 +75,18 @@ named!(categories<CompleteByteSlice, HashMap<&str, HashMap<&str,&str> > >,

#[test]
fn parse_category_test() {
let ini_file = CompleteByteSlice(
b"[category]
let ini_file = &b"[category]
parameter=value
key = value2",
);
key = value2"[..];

let ini_without_category = CompleteByteSlice(
b"\n\nparameter=value
key = value2",
);
let ini_without_category = &b"\n\nparameter=value
key = value2"[..];

let res = category(ini_file);
println!("{:?}", res);
match res {
Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i.0), o),
Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error"),
}

Expand All @@ -100,17 +95,15 @@ key = value2",

#[test]
fn parse_key_value_test() {
let ini_file = CompleteByteSlice(
b"parameter=value
key = value2",
);
let ini_file = &b"parameter=value
key = value2"[..];

let ini_without_key_value = CompleteByteSlice(b"\nkey = value2");
let ini_without_key_value = &b"\nkey = value2"[..];

let res = key_value(ini_file);
println!("{:?}", res);
match res {
Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i.0), o1, o2),
Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error"),
}

Expand All @@ -119,17 +112,15 @@ key = value2",

#[test]
fn parse_key_value_with_space_test() {
let ini_file = CompleteByteSlice(
b"parameter = value
key = value2",
);
let ini_file = &b"parameter = value
key = value2"[..];

let ini_without_key_value = CompleteByteSlice(b"\nkey = value2");
let ini_without_key_value = &b"\nkey = value2"[..];

let res = key_value(ini_file);
println!("{:?}", res);
match res {
Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i.0), o1, o2),
Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
_ => println!("error"),
}

Expand All @@ -138,12 +129,10 @@ key = value2",

#[test]
fn parse_key_value_with_comment_test() {
let ini_file = CompleteByteSlice(
b"parameter=value;abc
key = value2",
);
let ini_file = &b"parameter=value;abc
key = value2"[..];

let ini_without_key_value = CompleteByteSlice(b"\nkey = value2");
let ini_without_key_value = &b"\nkey = value2"[..];

let res = key_value(ini_file);
println!("{:?}", res);
Expand All @@ -157,20 +146,18 @@ key = value2",

#[test]
fn parse_multiple_keys_and_values_test() {
let ini_file = CompleteByteSlice(
b"parameter=value;abc
let ini_file = &b"parameter=value;abc
key = value2
[category]",
);
[category]"[..];

let ini_without_key_value = CompleteByteSlice(b"[category]");
let ini_without_key_value = &b"[category]"[..];

let res = keys_and_values(ini_file);
println!("{:?}", res);
match res {
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i.0), o),
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error"),
}

Expand All @@ -183,21 +170,19 @@ key = value2
#[test]
fn parse_category_then_multiple_keys_and_values_test() {
//FIXME: there can be an empty line or a comment line after a category
let ini_file = CompleteByteSlice(
b"[abcd]
let ini_file = &b"[abcd]
parameter=value;abc
key = value2
[category]",
);
[category]"[..];

let ini_after_parser = CompleteByteSlice(b"[category]");
let ini_after_parser = &b"[category]"[..];

let res = category_and_keys(ini_file);
println!("{:?}", res);
match res {
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i.0), o),
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error"),
}

Expand All @@ -209,8 +194,7 @@ key = value2

#[test]
fn parse_multiple_categories_test() {
let ini_file = CompleteByteSlice(
b"[abcd]
let ini_file = &b"[abcd]
parameter=value;abc
Expand All @@ -219,15 +203,14 @@ key = value2
[category]
parameter3=value3
key4 = value4
",
);
"[..];

let ini_after_parser = CompleteByteSlice(b"");
let ini_after_parser = &b""[..];

let res = categories(ini_file);
//println!("{:?}", res);
match res {
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i.0), o),
Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
_ => println!("error"),
}

Expand All @@ -244,7 +227,7 @@ key4 = value4
}

fn bench_ini_complete(c: &mut Criterion) {
let str = "[owner]
let s = "[owner]
name=John Doe
organization=Acme Widgets Inc.
Expand All @@ -259,42 +242,42 @@ file=payroll.dat
Benchmark::new(
"parse",
move |b| {
b.iter(|| categories(CompleteByteSlice(str.as_bytes())).unwrap());
b.iter(|| categories(s.as_bytes()).unwrap());
},
).throughput(Throughput::Bytes(str.len() as u32)),
).throughput(Throughput::Bytes(s.len() as u32)),
);
}

fn bench_ini_complete_keys_and_values(c: &mut Criterion) {
let str = "server=192.0.2.62
let s = "server=192.0.2.62
port=143
file=payroll.dat
";

named!(acc<CompleteByteSlice, Vec<(&str,&str)> >, many0!(key_value));
named!(acc<&[u8], Vec<(&str,&str)> >, many0!(key_value));

c.bench(
"bench ini complete keys and values",
Benchmark::new(
"parse",
move |b| {
b.iter(|| acc(CompleteByteSlice(str.as_bytes())).unwrap());
b.iter(|| acc(s.as_bytes()).unwrap());
},
).throughput(Throughput::Bytes(str.len() as u32)),
).throughput(Throughput::Bytes(s.len() as u32)),
);
}

fn bench_ini_complete_key_value(c: &mut Criterion) {
let str = "server=192.0.2.62\n";
let s = "server=192.0.2.62\n";

c.bench(
"bench ini complete key value",
Benchmark::new(
"parse",
move |b| {
b.iter(|| key_value(CompleteByteSlice(str.as_bytes())).unwrap());
b.iter(|| key_value(s.as_bytes()).unwrap());
},
).throughput(Throughput::Bytes(str.len() as u32)),
).throughput(Throughput::Bytes(s.len() as u32)),
);
}

Expand Down
Loading

0 comments on commit d85878e

Please sign in to comment.