Repository: Geal/nom
Pull request #1342 (2021-08-03 12:00:16)

[bench] http: function parser, fix deprecated bench


Patch:
diff --git a/Cargo.toml b/Cargo.toml
index ee7505e..1b1bbff 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -81,9 +81,6 @@ name = "custom_errors"
 [[test]]
 name = "float"
 
-[[test]]
-name = "inference"
-
 [[test]]
 name = "ini"
 required-features = ["alloc"]
@@ -107,18 +104,12 @@ required-features = ["alloc"]
 name = "multiline"
 required-features = ["alloc"]
 
-[[test]]
-name = "named_args"
-
 [[test]]
 name = "overflow"
 
 [[test]]
 name = "reborrow_fold"
 
-[[test]]
-name = "test1"
-
 [[test]]
 name = "fnmut"
 required-features = ["alloc"]
@@ -143,11 +134,6 @@ name = "ini"
 path = "benches/ini.rs"
 harness = false
 
-[[bench]]
-name = "ini_complete"
-path = "benches/ini_complete.rs"
-harness = false
-
 [[bench]]
 name = "ini_str"
 path = "benches/ini_str.rs"
diff --git a/README.md b/README.md
index 120c4c4..b2687ff 100644
--- a/README.md
+++ b/README.md
@@ -203,13 +203,6 @@ nom is available on [crates.io](https://crates.io/crates/nom) and can be include
 nom = "6"
 ```
 
-Then include it in your code like this:
-
-```rust,ignore
-#[macro_use]
-extern crate nom;
-```
-
 **NOTE: If you have existing code using nom below the 5.0 version, please take a look
 at the [upgrade documentation](https://github.com/Geal/nom/blob/master/doc/upgrading_to_nom_5.md)
 to handle the breaking changes.**
diff --git a/benches/http.rs b/benches/http.rs
index e17998b..c61f173 100644
--- a/benches/http.rs
+++ b/benches/http.rs
@@ -1,7 +1,5 @@
 #![cfg_attr(rustfmt, rustfmt_skip)]
 
-#[macro_use]
-extern crate nom;
 extern crate criterion;
 extern crate jemallocator;
 
@@ -9,7 +7,7 @@ extern crate jemallocator;
 static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
 
 use criterion::*;
-use nom::IResult;
+use nom::{IResult, bytes::complete::{tag, take_while1}, character::complete::{line_ending, char}, multi::many1};
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
 #[derive(Debug)]
@@ -72,60 +70,46 @@ fn is_version(c: u8) -> bool {
   c >= b'0' && c <= b'9' || c == b'.'
 }
 
-named!(line_ending, alt!(tag!("\r\n") | tag!("\n")));
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
 fn request_line(input: &[u8]) -> IResult<&[u8], Request> {
-  do_parse!(input,
-    method: take_while1!(is_token)     >>
-            take_while1!(is_space)     >>
-    url:    take_while1!(is_not_space) >>
-            take_while1!(is_space)     >>
-    version: http_version              >>
-    line_ending                        >>
+  let (input, method) = take_while1(is_token)(input)?;
+  let (input, _) = take_while1(is_space)(input)?;
+  let (input, uri) = take_while1(is_not_space)(input)?;
+  let (input, _) = take_while1(is_space)(input)?;
+  let (input, version) = http_version(input)?;
+  let (input, _) = line_ending(input)?;
 
-    (Request {
-        method: method,
-        uri:    url,
-        version: version,
-    }))
+  Ok((input, Request {method, uri, version}))
 }
 
-#[cfg_attr(rustfmt, rustfmt_skip)]
-named!(http_version, do_parse!(
-    tag!("HTTP/")                     >>
-    version: take_while1!(is_version) >>
+fn http_version(input: &[u8]) -> IResult<&[u8], &[u8]> {
+  let (input, _) = tag("HTTP/")(input)?;
+  let (input, version) = take_while1(is_version)(input)?;
 
-    (version)));
+  Ok((input, version))
+}
 
-#[cfg_attr(rustfmt, rustfmt_skip)]
-named!(message_header_value, do_parse!(
-          take_while1!(is_horizontal_space) >>
-    data: take_while1!(not_line_ending)     >>
-    line_ending                             >>
+fn message_header_value(input: &[u8]) -> IResult<&[u8], &[u8]> {
+  let (input, _) = take_while1(is_horizontal_space)(input)?;
+  let (input, data) = take_while1(not_line_ending)(input)?;
+  let (input, _) = line_ending(input)?;
 
-    (data)));
+  Ok((input, data))
+}
 
-#[cfg_attr(rustfmt, rustfmt_skip)]
 fn message_header(input: &[u8]) -> IResult<&[u8], Header> {
-  do_parse!(input,
-    name:   take_while1!(is_token)       >>
-            char!(':')                   >>
-    values: many1!(message_header_value) >>
+  let (input, name) = take_while1(is_token)(input)?;
+  let (input, _) = char(':')(input)?;
+  let (input, value) = many1(message_header_value)(input)?;
 
-    (Header {
-        name: name,
-        value: values,
-    }))
+  Ok((input, Header{ name, value }))
 }
 
 fn request(input: &[u8]) -> IResult<&[u8], (Request, Vec<Header>)> {
-  do_parse!(input,
-    req: request_line           >>
-    h:   many1!(message_header) >>
-         line_ending            >>
+  let (input, req) = request_line(input)?;
+  let (input, h) = many1(message_header)(input)?;
+  let (input, _) = line_ending(input)?;
 
-    (req, h))
+  Ok((input, (req, h)))
 }
 
 
@@ -183,15 +167,16 @@ Connection: keep-alive
 
 "[..];
 
-  c.bench(
-    "http",
-    Benchmark::new(
-      "parse",
-      move |b| {
-        b.iter(|| parse(data).unwrap());
-      },
-    ).throughput(Throughput::Bytes(data.len() as u64)),
-  );
+  let mut http_group = c.benchmark_group("http");
+  http_group.throughput(Throughput::Bytes(data.len() as u64));
+  http_group.bench_with_input(
+    BenchmarkId::new("parse", data.len()),
+     data,
+      |b, data| {
+    b.iter(|| parse(data).unwrap());
+  });
+
+  http_group.finish();
 }
 
 /*
diff --git a/benches/ini.rs b/benches/ini.rs
index f022e25..160eee9 100644
--- a/benches/ini.rs
+++ b/benches/ini.rs
@@ -1,5 +1,3 @@
-#[macro_use]
-extern crate nom;
 extern crate criterion;
 extern crate jemallocator;
 
@@ -13,8 +11,9 @@ use nom::{
   character::complete::{
     alphanumeric1 as alphanumeric, char, multispace1 as multispace, space1 as space,
   },
-  combinator::map_res,
-  sequence::delimited,
+  combinator::{map, map_res, opt},
+  multi::many0,
+  sequence::{delimited, pair, separated_pair, terminated, tuple},
   IResult,
 };
 use std::collections::HashMap;
@@ -27,208 +26,27 @@ fn category(i: &[u8]) -> IResult<&[u8], &str> {
   )(i)
 }
 
-named!(key_value    <&[u8],(&str,&str)>,
-  do_parse!(
-     key: map_res!(alphanumeric, str::from_utf8)
-  >>      opt!(space)
-  >>      char!('=')
-  >>      opt!(space)
-  >> val: map_res!(
-           take_while!(call!(|c| c != '\n' as u8 && c != ';' as u8)),
-           str::from_utf8
-         )
-  >>      opt!(pair!(char!(';'), take_while!(call!(|c| c != '\n' as u8))))
-  >>      (key, val)
-  )
-);
-
-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<&[u8],(&str,HashMap<&str,&str>)>,
-  do_parse!(
-    category: category         >>
-              opt!(multispace) >>
-    keys: keys_and_values      >>
-    (category, keys)
-  )
-);
-
-named!(categories<&[u8], HashMap<&str, HashMap<&str,&str> > >,
-  map!(
-    many0!(
-      separated_pair!(
-        category,
-        opt!(multispace),
-        map!(
-          many0!(terminated!(key_value, opt!(multispace))),
-          |vec: Vec<_>| vec.into_iter().collect()
-        )
-      )
-    ),
-    |vec: Vec<_>| vec.into_iter().collect()
-  )
-);
-
-/*
-#[test]
-fn parse_category_test() {
-  let ini_file = &b"[category]
-
-parameter=value
-key = value2"[..];
-
-  let ini_without_category = &b"parameter=value
-key = value2"[..];
-
-  let res = category(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
-    _ => println!("error")
-  }
-
-  assert_eq!(res, IResult::Done(ini_without_category, "category"));
+fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> {
+  let (i, key) = map_res(alphanumeric, str::from_utf8)(i)?;
+  let (i, _) = tuple((opt(space), char('='), opt(space)))(i)?;
+  let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8)(i)?;
+  let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n')))(i)?;
+  Ok((i, (key, val)))
 }
 
-#[test]
-fn parse_key_value_test() {
-  let ini_file = &b"parameter=value
-key = value2"[..];
-
-  let ini_without_key_value = &b"key = value2"[..];
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
-    _ => println!("error")
-  }
-
-  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
-}
-
-
-#[test]
-fn parse_key_value_with_space_test() {
-  let ini_file = &b"parameter = value
-key = value2"[..];
-
-  let ini_without_key_value = &b"key = value2"[..];
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
-    _ => println!("error")
-  }
-
-  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
-}
-
-#[test]
-fn parse_key_value_with_comment_test() {
-  let ini_file = &b"parameter=value;abc
-key = value2"[..];
-
-  let ini_without_key_value = &b"key = value2"[..];
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, (o1, o2)) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
-    _ => println!("error")
-  }
-
-  assert_eq!(res, IResult::Done(ini_without_key_value, ("parameter", "value")));
-}
-
-#[test]
-fn parse_multiple_keys_and_values_test() {
-  let ini_file = &b"parameter=value;abc
-
-key = value2
-
-[category]"[..];
-
-  let ini_without_key_value = &b"[category]"[..];
-
-  let res = keys_and_values(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
-    _ => println!("error")
-  }
-
-  let mut expected: HashMap<&str, &str> = HashMap::new();
-  expected.insert("parameter", "value");
-  expected.insert("key", "value2");
-  assert_eq!(res, IResult::Done(ini_without_key_value, expected));
-}
-
-#[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 = &b"[abcd]
-parameter=value;abc
-
-key = value2
-
-[category]"[..];
-
-  let ini_after_parser = &b"[category]"[..];
-
-  let res = category_and_keys(ini_file);
-  println!("{:?}", res);
-  match res {
-    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
-    _ => println!("error")
-  }
-
-  let mut expected_h: HashMap<&str, &str> = HashMap::new();
-  expected_h.insert("parameter", "value");
-  expected_h.insert("key", "value2");
-  assert_eq!(res, IResult::Done(ini_after_parser, ("abcd", expected_h)));
-}
-
-#[test]
-fn parse_multiple_categories_test() {
-  let ini_file = &b"[abcd]
-
-parameter=value;abc
-
-key = value2
-
-[category]
-parameter3=value3
-key4 = value4
-\0"[..];
-
-  let ini_after_parser = &b"\0"[..];
-
-  let res = categories(ini_file);
-  //println!("{:?}", res);
-  match res {
-    IResult::Done(i, ref o) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
-    _ => println!("error")
-  }
-
-  let mut expected_1: HashMap<&str, &str> = HashMap::new();
-  expected_1.insert("parameter", "value");
-  expected_1.insert("key", "value2");
-  let mut expected_2: HashMap<&str, &str> = HashMap::new();
-  expected_2.insert("parameter3", "value3");
-  expected_2.insert("key4", "value4");
-  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
-  expected_h.insert("abcd",     expected_1);
-  expected_h.insert("category", expected_2);
-  assert_eq!(res, IResult::Done(ini_after_parser, expected_h));
+fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> {
+  map(
+    many0(separated_pair(
+      category,
+      opt(multispace),
+      map(
+        many0(terminated(key_value, opt(multispace))),
+        |vec: Vec<_>| vec.into_iter().collect(),
+      ),
+    )),
+    |vec: Vec<_>| vec.into_iter().collect(),
+  )(i)
 }
-*/
 
 fn bench_ini(c: &mut Criterion) {
   let str = "[owner]
@@ -241,13 +59,11 @@ port=143
 file=payroll.dat
 \0";
 
-  c.bench(
-    "bench ini",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| categories(str.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(str.len() as u64)),
-  );
+  let mut group = c.benchmark_group("ini");
+  group.throughput(Throughput::Bytes(str.len() as u64));
+  group.bench_function(BenchmarkId::new("parse", str.len()), |b| {
+    b.iter(|| categories(str.as_bytes()).unwrap())
+  });
 }
 
 fn bench_ini_keys_and_values(c: &mut Criterion) {
@@ -256,27 +72,25 @@ port=143
 file=payroll.dat
 \0";
 
-  named!(acc<Vec<(&str, &str)>>, many0!(key_value));
+  fn acc(i: &[u8]) -> IResult<&[u8], Vec<(&str, &str)>> {
+    many0(key_value)(i)
+  }
 
-  c.bench(
-    "bench ini keys and values",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| acc(str.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(str.len() as u64)),
-  );
+  let mut group = c.benchmark_group("ini keys and values");
+  group.throughput(Throughput::Bytes(str.len() as u64));
+  group.bench_function(BenchmarkId::new("parse", str.len()), |b| {
+    b.iter(|| acc(str.as_bytes()).unwrap())
+  });
 }
 
 fn bench_ini_key_value(c: &mut Criterion) {
   let str = "server=192.0.2.62\n";
 
-  c.bench(
-    "bench ini key value",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| key_value(str.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(str.len() as u64)),
-  );
+  let mut group = c.benchmark_group("ini key value");
+  group.throughput(Throughput::Bytes(str.len() as u64));
+  group.bench_function(BenchmarkId::new("parse", str.len()), |b| {
+    b.iter(|| key_value(str.as_bytes()).unwrap())
+  });
 }
 
 criterion_group!(
diff --git a/benches/ini_complete.rs b/benches/ini_complete.rs
deleted file mode 100644
index a847ef4..0000000
--- a/benches/ini_complete.rs
+++ /dev/null
@@ -1,303 +0,0 @@
-#[macro_use]
-extern crate nom;
-extern crate criterion;
-extern crate jemallocator;
-
-#[global_allocator]
-static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
-
-use criterion::*;
-use nom::{
-  bytes::complete::take_while,
-  character::complete::{
-    alphanumeric1 as alphanumeric, char, multispace1 as multispace, space1 as space,
-  },
-  combinator::map_res,
-  sequence::delimited,
-  IResult,
-};
-use std::collections::HashMap;
-use std::str;
-
-/*
-named!(category<&[u8], &str>, map_res!(
-    delimited!(
-      char!('['),
-      take_while!(call!(|c| c != b']')),
-      char!(']')
-    ),
-    complete_byte_slice_to_str
-));
-
-fn complete_byte_slice_to_str<'a>(s: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
-  str::from_utf8(s)
-}
-*/
-
-fn category(i: &[u8]) -> IResult<&[u8], &str> {
-  map_res(
-    delimited(char('['), take_while(|c| c != b']'), char(']')),
-    str::from_utf8,
-  )(i)
-}
-
-fn complete_byte_slice_to_str<'a>(s: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
-  str::from_utf8(s)
-}
-
-named!(key_value    <&[u8],(&str,&str)>,
-  do_parse!(
-     key: map_res!(alphanumeric, complete_byte_slice_to_str)
-  >>      opt!(space)
-  >>      char!('=')
-  >>      opt!(space)
-  >> val: map_res!(
-           take_while!(call!(|c| c != b'\n' && c != b';')),
-           complete_byte_slice_to_str
-         )
-  >>      opt!(pair!(char!(';'), take_while!(call!(|c| c != b'\n'))))
-  >>      (key, val)
-  )
-);
-
-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<&[u8],(&str,HashMap<&str,&str>)>,
-  do_parse!(
-    category: category         >>
-              opt!(multispace) >>
-    keys: keys_and_values      >>
-    (category, keys)
-  )
-);
-
-named!(categories<&[u8], HashMap<&str, HashMap<&str,&str> > >,
-  map!(
-    many0!(
-      separated_pair!(
-        category,
-        opt!(multispace),
-        map!(
-          many0!(terminated!(key_value, opt!(multispace))),
-          |vec: Vec<_>| vec.into_iter().collect()
-        )
-      )
-    ),
-    |vec: Vec<_>| vec.into_iter().collect()
-  )
-);
-
-#[test]
-fn parse_category_test() {
-  let ini_file = &b"[category]
-
-parameter=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), o),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_category, "category")));
-}
-
-#[test]
-fn parse_key_value_test() {
-  let ini_file = &b"parameter=value
-key = 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), o1, o2),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_key_value_with_space_test() {
-  let ini_file = &b"parameter = value
-key = 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), o1, o2),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_key_value_with_comment_test() {
-  let ini_file = &b"parameter=value;abc
-key = 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),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_multiple_keys_and_values_test() {
-  let ini_file = &b"parameter=value;abc
-
-key = value2
-
-[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), o),
-    _ => println!("error"),
-  }
-
-  let mut expected: HashMap<&str, &str> = HashMap::new();
-  expected.insert("parameter", "value");
-  expected.insert("key", "value2");
-  assert_eq!(res, Ok((ini_without_key_value, expected)));
-}
-
-#[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 = &b"[abcd]
-parameter=value;abc
-
-key = value2
-
-[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), o),
-    _ => println!("error"),
-  }
-
-  let mut expected_h: HashMap<&str, &str> = HashMap::new();
-  expected_h.insert("parameter", "value");
-  expected_h.insert("key", "value2");
-  assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h))));
-}
-
-#[test]
-fn parse_multiple_categories_test() {
-  let ini_file = &b"[abcd]
-
-parameter=value;abc
-
-key = value2
-
-[category]
-parameter3=value3
-key4 = value4
-"[..];
-
-  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), o),
-    _ => println!("error"),
-  }
-
-  let mut expected_1: HashMap<&str, &str> = HashMap::new();
-  expected_1.insert("parameter", "value");
-  expected_1.insert("key", "value2");
-  let mut expected_2: HashMap<&str, &str> = HashMap::new();
-  expected_2.insert("parameter3", "value3");
-  expected_2.insert("key4", "value4");
-  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
-  expected_h.insert("abcd", expected_1);
-  expected_h.insert("category", expected_2);
-  assert_eq!(res, Ok((ini_after_parser, expected_h)));
-}
-
-fn bench_ini_complete(c: &mut Criterion) {
-  let s = "[owner]
-name=John Doe
-organization=Acme Widgets Inc.
-
-[database]
-server=192.0.2.62
-port=143
-file=payroll.dat
-";
-
-  c.bench(
-    "bench ini complete",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| categories(s.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(s.len() as u64)),
-  );
-}
-
-fn bench_ini_complete_keys_and_values(c: &mut Criterion) {
-  let s = "server=192.0.2.62
-port=143
-file=payroll.dat
-";
-
-  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(s.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(s.len() as u64)),
-  );
-}
-
-fn bench_ini_complete_key_value(c: &mut Criterion) {
-  let s = "server=192.0.2.62\n";
-
-  c.bench(
-    "bench ini complete key value",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| key_value(s.as_bytes()).unwrap());
-    })
-    .throughput(Throughput::Bytes(s.len() as u64)),
-  );
-}
-
-criterion_group!(
-  benches,
-  bench_ini_complete,
-  bench_ini_complete_keys_and_values,
-  bench_ini_complete_key_value
-);
-criterion_main!(benches);
diff --git a/benches/ini_str.rs b/benches/ini_str.rs
index 456dc55..044f679 100644
--- a/benches/ini_str.rs
+++ b/benches/ini_str.rs
@@ -1,18 +1,17 @@
-#[macro_use]
-extern crate nom;
 extern crate criterion;
 extern crate jemallocator;
 
-use criterion::*;
-
 #[global_allocator]
 static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
 
+use criterion::*;
+
 use nom::{
-  bytes::complete::{is_a, take_while},
+  bytes::complete::{is_a, tag, take_till, take_while},
   character::complete::{alphanumeric1 as alphanumeric, char, not_line_ending, space0 as space},
   combinator::opt,
-  sequence::{delimited, terminated},
+  multi::many0,
+  sequence::{delimited, pair, terminated, tuple},
   IResult,
 };
 
@@ -33,21 +32,19 @@ fn category(i: &str) -> IResult<&str, &str> {
   )(i)
 }
 
-named!(key_value    <&str,(&str,&str)>,
-  do_parse!(
-    key: alphanumeric                              >>
-         opt!(space)                               >>
-         tag!("=")                               >>
-         opt!(space)                               >>
-    val: take_till!(is_line_ending_or_comment)   >>
-         opt!(space)                               >>
-         opt!(pair!(tag!(";"), not_line_ending)) >>
-         opt!(space_or_line_ending)                >>
-    (key, val)
-  )
-);
-
-named!(keys_and_values_aggregator<&str, Vec<(&str, &str)> >, many0!(key_value));
+fn key_value(i: &str) -> IResult<&str, (&str, &str)> {
+  let (i, key) = alphanumeric(i)?;
+  let (i, _) = tuple((opt(space), tag("="), opt(space)))(i)?;
+  let (i, val) = take_till(is_line_ending_or_comment)(i)?;
+  let (i, _) = opt(space)(i)?;
+  let (i, _) = opt(pair(tag(";"), not_line_ending))(i)?;
+  let (i, _) = opt(space_or_line_ending)(i)?;
+  Ok((i, (key, val)))
+}
+
+fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> {
+  many0(key_value)(i)
+}
 
 fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> {
   match keys_and_values_aggregator(input) {
@@ -56,11 +53,13 @@ fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> {
   }
 }
 
-named!(category_and_keys<&str,(&str,HashMap<&str,&str>)>,
-  pair!(category, keys_and_values)
-);
+fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> {
+  pair(category, keys_and_values)(i)
+}
 
-named!(categories_aggregator<&str, Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
+fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> {
+  many0(category_and_keys)(i)
+}
 
 fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> {
   match categories_aggregator(input) {
@@ -69,157 +68,6 @@ fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>>
   }
 }
 
-#[test]
-fn parse_category_test() {
-  let ini_file = "[category]
-
-parameter=value
-key = value2";
-
-  let ini_without_category = "parameter=value
-key = value2";
-
-  let res = category(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, o)) => println!("i: {} | o: {:?}", i.0, o),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_category, "category")));
-}
-
-#[test]
-fn parse_key_value_test() {
-  let ini_file = "parameter=value
-key = value2";
-
-  let ini_without_key_value = "key = value2";
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i.0, o1, o2),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_key_value_with_space_test() {
-  let ini_file = "parameter = value
-key = value2";
-
-  let ini_without_key_value = "key = value2";
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i.0, o1, o2),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_key_value_with_comment_test() {
-  let ini_file = "parameter=value;abc
-key = value2";
-
-  let ini_without_key_value = "key = value2";
-
-  let res = key_value(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i.0, o1, o2),
-    _ => println!("error"),
-  }
-
-  assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
-}
-
-#[test]
-fn parse_multiple_keys_and_values_test() {
-  let ini_file = "parameter=value;abc
-
-key = value2
-
-[category]";
-
-  let ini_without_key_value = "[category]";
-
-  let res = keys_and_values(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, ref o)) => println!("i: {} | o: {:?}", i.0, o),
-    _ => println!("error"),
-  }
-
-  let mut expected: HashMap<&str, &str> = HashMap::new();
-  expected.insert("parameter", "value");
-  expected.insert("key", "value2");
-  assert_eq!(res, Ok((ini_without_key_value, expected)));
-}
-
-#[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 = "[abcd]
-parameter=value;abc
-
-key = value2
-
-[category]";
-
-  let ini_after_parser = "[category]";
-
-  let res = category_and_keys(ini_file);
-  println!("{:?}", res);
-  match res {
-    Ok((i, ref o)) => println!("i: {} | o: {:?}", i.0, o),
-    _ => println!("error"),
-  }
-
-  let mut expected_h: HashMap<&str, &str> = HashMap::new();
-  expected_h.insert("parameter", "value");
-  expected_h.insert("key", "value2");
-  assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h))));
-}
-
-#[test]
-fn parse_multiple_categories_test() {
-  let ini_file = "[abcd]
-
-parameter=value;abc
-
-key = value2
-
-[category]
-parameter3=value3
-key4 = value4
-";
-
-  let res = categories(ini_file);
-  //println!("{:?}", res);
-  match res {
-    Ok((i, ref o)) => println!("i: {} | o: {:?}", i.0, o),
-    _ => println!("error"),
-  }
-
-  let mut expected_1: HashMap<&str, &str> = HashMap::new();
-  expected_1.insert("parameter", "value");
-  expected_1.insert("key", "value2");
-  let mut expected_2: HashMap<&str, &str> = HashMap::new();
-  expected_2.insert("parameter3", "value3");
-  expected_2.insert("key4", "value4");
-  let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
-  expected_h.insert("abcd", expected_1);
-  expected_h.insert("category", expected_2);
-  assert_eq!(res, Ok(("", expected_h)));
-}
-
 fn bench_ini_str(c: &mut Criterion) {
   let s = "[owner]
 name=John Doe
@@ -231,13 +79,11 @@ port=143
 file=payroll.dat
 ";
 
-  c.bench(
-    "bench ini str",
-    Benchmark::new("parse", move |b| {
-      b.iter(|| categories(s).unwrap());
-    })
-    .throughput(Throughput::Bytes(s.len() as u64)),
-  );
+  let mut group = c.benchmark_group("ini str");
+  group.throughput(Throughput::Bytes(s.len() as u64));
+  group.bench_function(BenchmarkId::new("parse", s.len()), |b| {
+    b.iter(|| categories(s).unwrap())
+  });
 }
 
 criterion_group!(benches, bench_ini_str);
diff --git a/doc/nom_recipes.md b/doc/nom_recipes.md
index 3507e88..8899485 100644
--- a/doc/nom_recipes.md
+++ b/doc/nom_recipes.md
@@ -25,6 +25,14 @@ These are short recipes for accomplishing common tasks with nom.
 ### Wrapper combinators that eat whitespace before and after a parser
 
 ```rust
+use nom::{
+  IResult,
+  error::ParseError,
+  combinator::value,
+  sequence::delimited,
+  character::complete::multispace0,
+};
+
 /// A combinator that takes a parser `inner` and produces a parser that also consumes both leading and 
 /// trailing whitespace, returning the output of `inner`.
 fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
@@ -52,6 +60,15 @@ This version uses `%` to start a comment, does not consume the newline character
 output of `()`.
 
 ```rust
+use nom::{
+  IResult,
+  error::ParseError,
+  combinator::value,
+  sequence::pair,
+  bytes::complete::is_not,
+  character::complete::char,
+};
+
 pub fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E>
 {
   value(
@@ -67,6 +84,14 @@ Inline comments surrounded with sentinel tags `(*` and `*)`. This version return
 and does not handle nested comments.
 
 ```rust
+use nom::{
+  IResult,
+  error::ParseError,
+  combinator::value,
+  sequence::tuple,
+  bytes::complete::{tag, take_until},
+};
+
 pub fn pinline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
   value(
     (), // Output is thrown away.
@@ -87,6 +112,16 @@ Parsing identifiers that may start with a letter (or underscore) and may contain
 letters and numbers may be parsed like this:
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::many0,
+  combinator::recognize,
+  sequence::pair,
+  character::complete::{alpha1, alphanumeric1},
+  bytes::complete::tag,
+};
+
 pub fn identifier(input: &str) -> IResult<&str, &str> {
   recognize(
     pair(
@@ -128,6 +163,16 @@ If you wish to limit the number of digits in a valid integer literal, replace `m
 The parser outputs the string slice of the digits without the leading `0x`/`0X`.
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::{many0, many1},
+  combinator::recognize,
+  sequence::{preceded, terminated},
+  character::complete::{char, one_of},
+  bytes::complete::tag,
+};
+
 fn hexadecimal(input: &str) -> IResult<&str, &str> { // <'a, E: ParseError<&'a str>>
   preceded(
     alt((tag("0x"), tag("0X"))),
@@ -143,6 +188,16 @@ fn hexadecimal(input: &str) -> IResult<&str, &str> { // <'a, E: ParseError<&'a s
 If you want it to return the integer value instead, use map:
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::{many0, many1},
+  combinator::{map_res, recognize},
+  sequence::{preceded, terminated},
+  character::complete::{char, one_of},
+  bytes::complete::tag,
+};
+
 fn hexadecimal_value(input: &str) -> IResult<&str, i64> {
   map_res(
     preceded(
@@ -161,6 +216,16 @@ fn hexadecimal_value(input: &str) -> IResult<&str, i64> {
 #### Octal
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::{many0, many1},
+  combinator::recognize,
+  sequence::{preceded, terminated},
+  character::complete::{char, one_of},
+  bytes::complete::tag,
+};
+
 fn octal(input: &str) -> IResult<&str, &str> {
   preceded(
     alt((tag("0o"), tag("0O"))),
@@ -176,6 +241,16 @@ fn octal(input: &str) -> IResult<&str, &str> {
 #### Binary
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::{many0, many1},
+  combinator::recognize,
+  sequence::{preceded, terminated},
+  character::complete::{char, one_of},
+  bytes::complete::tag,
+};
+
 fn binary(input: &str) -> IResult<&str, &str> {
   preceded(
     alt((tag("0b"), tag("0B"))),
@@ -191,6 +266,14 @@ fn binary(input: &str) -> IResult<&str, &str> {
 #### Decimal
 
 ```rust
+use nom::{
+  IResult,
+  multi::{many0, many1},
+  combinator::recognize,
+  sequence::terminated,
+  character::complete::{char, one_of},
+};
+
 fn decimal(input: &str) -> IResult<&str, &str> {
   recognize(
     many1(
@@ -205,6 +288,15 @@ fn decimal(input: &str) -> IResult<&str, &str> {
 The following is adapted from [the Python parser by Valentin Lorentz (ProgVal)](https://github.com/ProgVal/rust-python-parser/blob/master/src/numbers.rs).
 
 ```rust
+use nom::{
+  IResult,
+  branch::alt,
+  multi::{many0, many1},
+  combinator::{opt, recognize},
+  sequence::{preceded, terminated, tuple},
+  character::complete::{char, one_of},
+};
+
 fn float(input: &str) -> IResult<&str, &str> {
   alt((
     // Case one: .42
@@ -242,6 +334,14 @@ fn float(input: &str) -> IResult<&str, &str> {
     )
   ))(input)
 }
+
+fn decimal(input: &str) -> IResult<&str, &str> {
+  recognize(
+    many1(
+      terminated(one_of("0123456789"), many0(char('_')))
+    )
+  )(input)
+}
 ```
 
 # implementing FromStr
diff --git a/src/branch/macros.rs b/src/branch/macros.rs
deleted file mode 100644
index a9a3a33..0000000
--- a/src/branch/macros.rs
+++ /dev/null
@@ -1,954 +0,0 @@
-/// Try a list of parsers and return the result of the first successful one
-///
-/// ```rust,ignore
-/// alt!(I -> IResult<I,O> | I -> IResult<I,O> | ... | I -> IResult<I,O> ) => I -> IResult<I, O>
-/// ```
-/// All the parsers must have the same return type.
-///
-/// If one of the parsers returns `Incomplete`, `alt!` will return `Incomplete`, to retry
-/// once you get more input. Note that it is better for performance to know the
-/// minimum size of data you need before you get into `alt!`.
-///
-/// The `alt!` combinator is used in the following way:
-///
-/// ```rust,ignore
-/// alt!(parser_1 | parser_2 | ... | parser_n)
-/// ```
-///
-/// # Basic example
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # fn main() {
-///  // Create a parser that will match either "dragon" or "beast"
-///  named!( dragon_or_beast, alt!( tag!( "dragon" ) | tag!( "beast" ) ) );
-///
-///  // Given the input "dragon slayer", the parser will match "dragon"
-///  // and the rest will be " slayer"
-///  let (rest, result) = dragon_or_beast(b"dragon slayer").unwrap();
-///  assert_eq!(result, b"dragon");
-///  assert_eq!(rest, b" slayer");
-///
-///  // Given the input "beast of Gevaudan", the parser will match "beast"
-///  // and the rest will be " of Gevaudan"
-///  let (rest, result) = dragon_or_beast(&b"beast of Gevaudan"[..]).unwrap();
-///  assert_eq!(result, b"beast");
-///  assert_eq!(rest, b" of Gevaudan");
-///  # }
-/// ```
-///
-/// # Manipulate results
-///
-/// There exists another syntax for `alt!` that gives you the ability to
-/// manipulate the result from each parser:
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # fn main() {
-/// #
-/// // We create an enum to represent our creatures
-/// #[derive(Debug,PartialEq,Eq)]
-/// enum Creature {
-///     Dragon,
-///     Beast,
-///     Unknown(usize)
-/// }
-///
-/// // Let's make a helper function that returns true when not a space
-/// // we are required to do this because the `take_while!` macro is limited
-/// // to idents, so we can't negate `ìs_space` at the call site
-/// fn is_not_space(c: u8) -> bool { ! nom::character::is_space(c) }
-///
-/// // Our parser will return the `Dragon` variant when matching "dragon",
-/// // the `Beast` variant when matching "beast" and otherwise it will consume
-/// // the input until a space is found and return an `Unknown` creature with
-/// // the size of it's name.
-/// named!(creature<Creature>, alt!(
-///     tag!("dragon")            => { |_| Creature::Dragon } |
-///     tag!("beast")             => { |_| Creature::Beast }  |
-///     take_while!(is_not_space) => { |r: &[u8]| Creature::Unknown(r.len()) }
-///     // the closure takes the result as argument if the parser is successful
-/// ));
-///
-/// // Given the input "dragon slayer" the parser will return `Creature::Dragon`
-/// // and the rest will be " slayer"
-/// let (rest, result) = creature(b"dragon slayer").unwrap();
-/// assert_eq!(result, Creature::Dragon);
-/// assert_eq!(rest, b" slayer");
-///
-/// // Given the input "beast of Gevaudan" the parser will return `Creature::Beast`
-/// // and the rest will be " of Gevaudan"
-/// let (rest, result) = creature(b"beast of Gevaudan").unwrap();
-/// assert_eq!(result, Creature::Beast);
-/// assert_eq!(rest, b" of Gevaudan");
-///
-/// // Given the input "demon hunter" the parser will return `Creature::Unknown(5)`
-/// // and the rest will be " hunter"
-/// let (rest, result) = creature(b"demon hunter").unwrap();
-/// assert_eq!(result, Creature::Unknown(5));
-/// assert_eq!(rest, b" hunter");
-/// # }
-/// ```
-///
-/// # Behaviour of `alt!`
-///
-/// **BE CAREFUL** there is a case where the behaviour of `alt!` can be confusing:
-///
-/// When the alternatives have different lengths, like this case:
-///
-/// ```ignore
-///  named!( test, alt!( tag!( "abcd" ) | tag!( "ef" ) | tag!( "ghi" ) | tag!( "kl" ) ) );
-/// ```
-///
-/// With this parser, if you pass `"abcd"` as input, the first alternative parses it correctly,
-/// but if you pass `"efg"`, the first alternative will return `Incomplete`, since it needs an input
-/// of 4 bytes. This behaviour of `alt!` is expected: if you get a partial input that isn't matched
-/// by the first alternative, but would match if the input was complete, you want `alt!` to indicate
-/// that it cannot decide with limited information.
-///
-/// There are two ways to fix this behaviour. The first one consists in ordering the alternatives
-/// by size, like this:
-///
-/// ```ignore
-///  named!( test, alt!( tag!( "ef" ) | tag!( "kl") | tag!( "ghi" ) | tag!( "abcd" ) ) );
-/// ```
-///
-/// With this solution, the largest alternative will be tested last.
-///
-/// The other solution uses the `complete!` combinator, which transforms an `Incomplete` in an
-/// `Error`. If one of the alternatives returns `Incomplete` but is wrapped by `complete!`,
-/// `alt!` will try the next alternative. This is useful when you know that
-/// you will not get partial input:
-///
-/// ```ignore
-///  named!( test,
-///    alt!(
-///      complete!( tag!( "abcd" ) ) |
-///      complete!( tag!( "ef"   ) ) |
-///      complete!( tag!( "ghi"  ) ) |
-///      complete!( tag!( "kl"   ) )
-///    )
-///  );
-/// ```
-///
-/// This behaviour of `alt!` can get especially confusing if multiple alternatives have different
-/// sizes but a common prefix, like this:
-///
-/// ```ignore
-///  named!( test, alt!( tag!( "abcd" ) | tag!( "ab" ) | tag!( "ef" ) ) );
-/// ```
-///
-/// In that case, if you order by size, passing `"abcd"` as input will always be matched by the
-/// smallest parser, so the solution using `complete!` is better suited.
-///
-/// You can also nest multiple `alt!`, like this:
-///
-/// ```ignore
-///  named!( test,
-///    alt!(
-///      preceded!(
-///        tag!("ab"),
-///        alt!(
-///          tag!( "cd" ) |
-///          eof!()
-///        )
-///      )
-///    | tag!( "ef" )
-///    )
-///  );
-/// ```
-///
-///  `preceded!` will first parse `"ab"` then, if successful, try the alternatives "cd",
-///  or empty input (End Of File). If none of them work, `preceded!` will fail and
-///  "ef" will be tested.
-///
-#[macro_export(local_inner_macros)]
-macro_rules! alt (
-  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)* ) => (
-    nom_compile_error!("alt uses '|' as separator, not ',':
-
-      alt!(
-        tag!(\"abcd\") |
-        tag!(\"efgh\") |
-        tag!(\"ijkl\")
-      )
-    ");
-  );
-  (__impl $i:expr, $e:path, $($rest:tt)* ) => (
-    alt!(__impl $i, call!($e) , $($rest)*);
-  );
-  (__impl $i:expr, $e:path | $($rest:tt)*) => (
-    alt!(__impl $i, call!($e) | $($rest)*);
-  );
-
-  (__impl $i:expr, $subrule:ident!( $($args:tt)*) | $($rest:tt)*) => (
-    {
-      use $crate::lib::std::result::Result::*;
-      use $crate::Err;
-
-      let i_ = $i.clone();
-      let res = $subrule!(i_, $($args)*);
-      match res {
-        Ok(o) => Ok(o),
-        Err(Err::Error(e))      => {
-          let out = alt!(__impl $i, $($rest)*);
-
-          // Compile-time hack to ensure that res's E type is not under-specified.
-          // This all has no effect at runtime.
-          #[allow(dead_code)]
-          fn unify_types<T>(_: &T, _: &T) {}
-          if let Err(Err::Error(ref e2)) = out {
-            unify_types(&e, e2);
-          }
-
-          out
-        },
-        Err(e) => Err(e),
-      }
-    }
-  );
-
-  (__impl $i:expr, $subrule:ident!( $($args:tt)* ) => { $gen:expr } | $($rest:tt)*) => (
-    {
-      use $crate::lib::std::result::Result::*;
-      use $crate::Err;
-
-      let i_ = $i.clone();
-      match $subrule!(i_, $($args)* ) {
-        Ok((i,o))         => Ok((i,$gen(o))),
-        Err(Err::Error(e)) => {
-          let out = alt!(__impl $i, $($rest)*);
-
-          // Compile-time hack to ensure that res's E type is not under-specified.
-          // This all has no effect at runtime.
-          fn unify_types<T>(_: &T, _: &T) {}
-          if let Err(Err::Error(ref e2)) = out {
-            unify_types(&e, e2);
-          }
-
-          out
-        },
-        Err(e) => Err(e),
-      }
-    }
-  );
-
-  (__impl $i:expr, $e:path => { $gen:expr } | $($rest:tt)*) => (
-    alt!(__impl $i, call!($e) => { $gen } | $($rest)*);
-  );
-
-  (__impl $i:expr, __end) => (
-    {
-      use $crate::{Err,error::ErrorKind};
-      let e2 = ErrorKind::Alt;
-      let err = Err::Error(error_position!($i, e2));
-
-      Err(err)
-    }
-  );
-
-  ($i:expr, $($rest:tt)*) => (
-    {
-      alt!(__impl $i, $($rest)* | __end)
-    }
-  );
-);
-
-/// `switch!(I -> IResult<I,P>, P => I -> IResult<I,O> | ... | P => I -> IResult<I,O> ) => I -> IResult<I, O>`
-/// choose the next parser depending on the result of the first one, if successful,
-/// and returns the result of the second parser
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(sw,
-///    switch!(take!(4),
-///      b"abcd" => tag!("XYZ") |
-///      b"efgh" => tag!("123")
-///    )
-///  );
-///
-///  let a = b"abcdXYZ123";
-///  let b = b"abcdef";
-///  let c = b"efgh123";
-///  let d = b"blah";
-///
-///  assert_eq!(sw(&a[..]), Ok((&b"123"[..], &b"XYZ"[..])));
-///  assert_eq!(sw(&b[..]), Err(Err::Error(error_node_position!(&b"abcdef"[..], ErrorKind::Switch,
-///    error_position!(&b"ef"[..], ErrorKind::Tag)))));
-///  assert_eq!(sw(&c[..]), Ok((&b""[..], &b"123"[..])));
-///  assert_eq!(sw(&d[..]), Err(Err::Error(error_position!(&b"blah"[..], ErrorKind::Switch))));
-///  # }
-/// ```
-///
-/// You can specify a default case like with a normal match, using `_`
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # fn main() {
-///  named!(sw,
-///    switch!(take!(4),
-///      b"abcd" => tag!("XYZ") |
-///      _       => value!(&b"default"[..])
-///    )
-///  );
-///
-///  let a = b"abcdXYZ123";
-///  let b = b"blah";
-///
-///  assert_eq!(sw(&a[..]), Ok((&b"123"[..], &b"XYZ"[..])));
-///  assert_eq!(sw(&b[..]), Ok((&b""[..], &b"default"[..])));
-///  # }
-/// ```
-///
-/// Due to limitations in Rust macros, it is not possible to have simple functions on the right hand
-/// side of pattern, like this:
-///
-/// ```ignore
-///  named!(xyz, tag!("XYZ"));
-///  named!(num, tag!("123"));
-///  named!(sw,
-///    switch!(take!(4),
-///      b"abcd" => xyz |
-///      b"efgh" => 123
-///    )
-///  );
-/// ```
-///
-/// If you want to pass your own functions instead, you can use the `call!` combinator as follows:
-///
-/// ```ignore
-///  named!(xyz, tag!("XYZ"));
-///  named!(num, tag!("123"));
-///  named!(sw,
-///    switch!(take!(4),
-///      b"abcd" => call!(xyz) |
-///      b"efgh" => call!(num)
-///    )
-///  );
-/// ```
-///
-#[macro_export(local_inner_macros)]
-macro_rules! switch (
-  (__impl $i:expr, $submac:ident!( $($args:tt)* ), $( $($p:pat)|+ => $subrule:ident!( $($args2:tt)* ))|* ) => (
-    {
-      use $crate::lib::std::result::Result::*;
-      use $crate::lib::std::option::Option::*;
-      use $crate::{Err,error::ErrorKind};
-
-      let i_ = $i.clone();
-      match map!(i_, $submac!($($args)*), Some) {
-        Err(Err::Error(err))      => {
-          fn unify_types<T>(_: &T, _: &T) {}
-          let e1 = ErrorKind::Switch;
-          let e2 = error_position!($i, e1.clone());
-          unify_types(&err, &e2);
-
-          Err(Err::Error(error_node_position!($i, e1, err)))
-        },
-        Err(e) => Err(e),
-        Ok((i, o))    => {
-
-          match o {
-            $($(Some($p) )|+ => match $subrule!(i, $($args2)*) {
-              Err(Err::Error(err)) => {
-                fn unify_types<T>(_: &T, _: &T) {}
-                let e1 = ErrorKind::Switch;
-                let e2 = error_position!($i, e1.clone());
-                unify_types(&err, &e2);
-
-                Err(Err::Error(error_node_position!($i, e1, err)))
-              },
-              Ok(o) => Ok(o),
-              Err(e) => Err(e),
-            }),*,
-            _    => Err(Err::convert(Err::Error(error_position!($i, ErrorKind::Switch))))
-          }
-        }
-      }
-    }
-  );
-  ($i:expr, $submac:ident!( $($args:tt)*), $($rest:tt)*) => (
-    {
-      switch!(__impl $i, $submac!($($args)*), $($rest)*)
-    }
-  );
-  ($i:expr, $e:path, $($rest:tt)*) => (
-    {
-      switch!(__impl $i, call!($e), $($rest)*)
-    }
-  );
-);
-
-/// `permutation!(I -> IResult<I,A>, I -> IResult<I,B>, ... I -> IResult<I,X> ) => I -> IResult<I, (A,B,...X)>`
-/// applies its sub parsers in a sequence, but independent from their order
-/// this parser will only succeed if all of its sub parsers succeed.
-///
-/// The tuple of results is in the same order as the parsers are declared
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err,error::ErrorKind,Needed};
-/// # fn main() {
-/// named!(perm<(&[u8], &[u8], &[u8])>,
-///   permutation!(tag!("abcd"), tag!("efg"), tag!("hi"))
-/// );
-///
-/// // whatever the order, if the parser succeeds, each
-/// // tag should have matched correctly
-/// let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
-///
-/// let a = &b"abcdefghijk"[..];
-/// assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
-/// let b = &b"efgabcdhijkl"[..];
-/// assert_eq!(perm(b), Ok((&b"jkl"[..], expected)));
-/// let c = &b"hiefgabcdjklm"[..];
-/// assert_eq!(perm(c), Ok((&b"jklm"[..], expected)));
-///
-/// let d = &b"efgxyzabcdefghi"[..];
-/// assert_eq!(perm(d), Err(Err::Error(error_node_position!(&b"efgxyzabcdefghi"[..], ErrorKind::Permutation,
-///   error_position!(&b"xyzabcdefghi"[..], ErrorKind::Permutation)))));
-///
-/// let e = &b"efgabc"[..];
-/// assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
-/// # }
-/// ```
-///
-/// If one of the child parsers is followed by a `?`, that parser is now
-/// optional:
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err,error::ErrorKind,Needed};
-/// # fn main() {
-/// named!(perm<&str, (Option<&str>, &str, &str)>,
-///   permutation!(tag!("abcd")?, tag!("efg"), tag!("hi"))
-/// );
-///
-/// // whatever the order, if the parser succeeds, each
-/// // tag should have matched correctly
-/// let expected = (Some("abcd"), "efg", "hi");
-///
-/// let a = "abcdefghijk";
-/// assert_eq!(perm(a), Ok(("jk", expected)));
-/// let b = "efgabcdhijkl";
-/// assert_eq!(perm(b), Ok(("jkl", expected)));
-/// let c = "hiefgabcdjklm";
-/// assert_eq!(perm(c), Ok(("jklm", expected)));
-///
-/// // if `abcd` is missing:
-/// let expected = (None, "efg", "hi");
-///
-/// let a = "efghijk";
-/// assert_eq!(perm(a), Ok(("jk", expected)));
-/// let b = "efghijkl";
-/// assert_eq!(perm(b), Ok(("jkl", expected)));
-/// let c = "hiefgjklm";
-/// assert_eq!(perm(c), Ok(("jklm", expected)));
-///
-/// let e = "efgabc";
-/// assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! permutation (
-  ($i:expr, $($rest:tt)*) => (
-    {
-      use $crate::lib::std::result::Result::*;
-      use $crate::lib::std::option::Option::*;
-      use $crate::{Err,error::ErrorKind};
-
-      let mut res    = permutation_init!((), $($rest)*);
-      let mut input  = $i;
-      let mut error  = None;
-      let mut needed = None;
-
-      loop {
-        let mut all_done = true;
-        permutation_iterator!(0, input, all_done, needed, res, $($rest)*);
-
-        //if we reach that part, it means none of the parsers were able to read anything
-        if !all_done {
-          //FIXME: should wrap the error returned by the child parser
-          error = Some(error_position!(input, ErrorKind::Permutation));
-        }
-        break;
-      }
-
-      if let Some(need) = needed {
-        Err(Err::convert(need))
-      } else {
-        if let Some(unwrapped_res) = { permutation_unwrap!(0, (), res, $($rest)*) } {
-          Ok((input, unwrapped_res))
-        } else {
-          if let Some(e) = error {
-            Err(Err::Error(error_node_position!($i, ErrorKind::Permutation, e)))
-          } else {
-            Err(Err::Error(error_position!($i, ErrorKind::Permutation)))
-          }
-        }
-      }
-    }
-  );
-);
-
-#[doc(hidden)]
-#[macro_export(local_inner_macros)]
-macro_rules! permutation_init (
-  ((), $e:ident?, $($rest:tt)*) => (
-    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
-  );
-  ((), $e:ident, $($rest:tt)*) => (
-    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
-  );
-
-  ((), $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
-    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
-  );
-  ((), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
-    permutation_init!(($crate::lib::std::option::Option::None), $($rest)*)
-  );
-
-  (($($parsed:expr),*), $e:ident?, $($rest:tt)*) => (
-    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
-  );
-  (($($parsed:expr),*), $e:ident, $($rest:tt)*) => (
-    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
-  );
-
-  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
-    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
-  );
-  (($($parsed:expr),*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
-    permutation_init!(($($parsed),* , $crate::lib::std::option::Option::None), $($rest)*);
-  );
-
-  (($($parsed:expr),*), $e:ident) => (
-    ($($parsed),* , $crate::lib::std::option::Option::None)
-  );
-  (($($parsed:expr),*), $e:ident?) => (
-    ($($parsed),* , $crate::lib::std::option::Option::None)
-  );
-
-  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )?) => (
-    ($($parsed),* , $crate::lib::std::option::Option::None)
-  );
-  (($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
-    ($($parsed),* , $crate::lib::std::option::Option::None)
-  );
-  (($($parsed:expr),*),) => (
-    ($($parsed),*)
-  );
-);
-
-#[doc(hidden)]
-#[macro_export(local_inner_macros)]
-macro_rules! succ (
-  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
-  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
-  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
-  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
-  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
-  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
-  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
-  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
-  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
-  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
-  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
-  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
-  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
-  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
-  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
-  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
-  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
-  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
-  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
-  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
-  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
-);
-
-#[doc(hidden)]
-#[macro_export(local_inner_macros)]
-macro_rules! permutation_unwrap (
-  ($it:tt,  (), $res:ident, $e:ident?, $($rest:tt)*) => (
-    succ!($it, permutation_unwrap!(($res.$it), $res, $($rest)*));
-  );
-  ($it:tt,  (), $res:ident, $e:ident, $($rest:tt)*) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      succ!($it, permutation_unwrap!((res.unwrap()), $res, $($rest)*))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-
-  ($it:tt,  (), $res:ident, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
-    succ!($it, permutation_unwrap!(($res.$it), $res, $($rest)*));
-  );
-  ($it:tt,  (), $res:ident, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      succ!($it, permutation_unwrap!((res.unwrap()), $res, $($rest)*))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-
-  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident?, $($rest:tt)*) => (
-    succ!($it, permutation_unwrap!(($($parsed),* , $res.$it), $res, $($rest)*));
-  );
-  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident, $($rest:tt)*) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      succ!($it, permutation_unwrap!(($($parsed),* , res.unwrap()), $res, $($rest)*))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-
-  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => (
-    succ!($it, permutation_unwrap!(($($parsed),* , $res.$it), $res, $($rest)*));
-  );
-  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      succ!($it, permutation_unwrap!(($($parsed),* , res.unwrap()), $res, $($rest)*))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-
-  ($it:tt, ($($parsed:expr),*), $res:ident?, $e:ident) => (
-    $crate::lib::std::option::Option::Some(($($parsed),* , { $res.$it }))
-  );
-  ($it:tt, ($($parsed:expr),*), $res:ident, $e:ident) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-
-  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )?) => (
-    $crate::lib::std::option::Option::Some(($($parsed),* , { $res.$it }))
-  );
-  ($it:tt, ($($parsed:expr),*), $res:ident, $submac:ident!( $($args:tt)* )) => ({
-    let res = $res.$it;
-    if res.is_some() {
-      $crate::lib::std::option::Option::Some(($($parsed),* , res.unwrap() ))
-    } else {
-      $crate::lib::std::option::Option::None
-    }
-  });
-);
-
-#[doc(hidden)]
-#[macro_export(local_inner_macros)]
-macro_rules! permutation_iterator (
-  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident?, $($rest:tt)*) => (
-    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e), $($rest)*);
-  );
-  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident, $($rest:tt)*) => (
-    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e), $($rest)*);
-  );
-
-  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?, $($rest:tt)*) => {
-    permutation_iterator!($it, $i, $all_done, $needed, $res, $submac!($($args)*) , $($rest)*);
-  };
-  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* ), $($rest:tt)*) => ({
-    use $crate::lib::std::result::Result::*;
-    use $crate::lib::std::option::Option::*;
-    use $crate::Err;
-
-    if $res.$it.is_none() {
-      match $submac!($i, $($args)*) {
-        Ok((i,o))     => {
-          $i = i;
-          $res.$it = Some(o);
-          continue;
-        },
-        Err(Err::Error(_)) => {
-          $all_done = false;
-        },
-        Err(e) => {
-          $needed = Some(e);
-          break;
-        }
-      };
-    }
-    succ!($it, permutation_iterator!($i, $all_done, $needed, $res, $($rest)*));
-  });
-
-  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident?) => (
-    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e));
-  );
-  ($it:tt,$i:expr, $all_done:expr, $needed:expr, $res:expr, $e:ident) => (
-    permutation_iterator!($it, $i, $all_done, $needed, $res, call!($e));
-  );
-
-  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )?) => {
-    permutation_iterator!($it, $i, $all_done, $needed, $res, $submac!($($args)*));
-  };
-  ($it:tt, $i:expr, $all_done:expr, $needed:expr, $res:expr, $submac:ident!( $($args:tt)* )) => ({
-    use $crate::lib::std::result::Result::*;
-    use $crate::lib::std::option::Option::*;
-    use $crate::Err;
-
-    if $res.$it.is_none() {
-      match $submac!($i, $($args)*) {
-        Ok((i,o))     => {
-          $i = i;
-          $res.$it = Some(o);
-          continue;
-        },
-        Err(Err::Error(_)) => {
-          $all_done = false;
-        },
-        Err(e) => {
-          $needed = Some(e);
-          break;
-        }
-      };
-    }
-  });
-);
-
-#[cfg(test)]
-mod tests {
-  use crate::error::ErrorKind;
-  use crate::internal::{Err, IResult, Needed};
-  #[cfg(feature = "alloc")]
-  use crate::{
-    error::ParseError,
-    lib::std::{
-      fmt::Debug,
-      string::{String, ToString},
-    },
-  };
-
-  // reproduce the tag and take macros, because of module import order
-  macro_rules! tag (
-    ($i:expr, $inp: expr) => (
-      {
-        #[inline(always)]
-        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
-          b.as_bytes()
-        }
-
-        let expected = $inp;
-        let bytes    = as_bytes(&expected);
-
-        tag_bytes!($i,bytes)
-      }
-    );
-  );
-
-  macro_rules! tag_bytes (
-    ($i:expr, $bytes: expr) => (
-      {
-        use $crate::lib::std::cmp::min;
-
-        let len = $i.len();
-        let blen = $bytes.len();
-        let m   = min(len, blen);
-        let reduced = &$i[..m];
-        let b       = &$bytes[..m];
-
-        let res: IResult<_,_,_> = if reduced != b {
-          let e: ErrorKind = ErrorKind::Tag;
-          Err(Err::Error(error_position!($i, e)))
-        } else if m < blen {
-          Err(Err::Incomplete(Needed::new(blen)))
-        } else {
-          Ok((&$i[blen..], reduced))
-        };
-        res
-      }
-    );
-  );
-
-  macro_rules! take(
-    ($i:expr, $count:expr) => (
-      {
-        let cnt = $count as usize;
-        let res:IResult<&[u8],&[u8],_> = if $i.len() < cnt {
-          Err(Err::Incomplete(Needed::new(cnt)))
-        } else {
-          Ok((&$i[cnt..],&$i[0..cnt]))
-        };
-        res
-      }
-    );
-  );
-
-  #[cfg(feature = "alloc")]
-  #[derive(Debug, Clone, PartialEq)]
-  pub struct ErrorStr(String);
-
-  #[cfg(feature = "alloc")]
-  impl From<u32> for ErrorStr {
-    fn from(i: u32) -> Self {
-      ErrorStr(format!("custom error code: {}", i))
-    }
-  }
-
-  #[cfg(feature = "alloc")]
-  impl<'a> From<&'a str> for ErrorStr {
-    fn from(i: &'a str) -> Self {
-      ErrorStr(format!("custom error message: {}", i))
-    }
-  }
-
-  #[cfg(feature = "alloc")]
-  impl<I: Debug> ParseError<I> for ErrorStr {
-    fn from_error_kind(input: I, kind: ErrorKind) -> Self {
-      ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
-    }
-
-    fn append(input: I, kind: ErrorKind, other: Self) -> Self {
-      ErrorStr(format!(
-        "custom error message: ({:?}, {:?}) - {:?}",
-        input, kind, other
-      ))
-    }
-  }
-
-  #[cfg(feature = "alloc")]
-  #[test]
-  fn alt() {
-    fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      Ok((&b""[..], input))
-    }
-
-    #[allow(unused_variables)]
-    fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      Err(Err::Error(ErrorStr("abcd".to_string())))
-    }
-
-    fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      Ok((input, &b""[..]))
-    }
-
-    fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      alt!(i, dont_work | dont_work)
-    }
-    fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      alt!(i, dont_work | work)
-    }
-    fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
-      alt!(i, dont_work | dont_work | work2 | dont_work)
-    }
-    //named!(alt1, alt!(dont_work | dont_work));
-    //named!(alt2, alt!(dont_work | work));
-    //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work));
-
-    let a = &b"abcd"[..];
-    assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Alt))));
-    assert_eq!(alt2(a), Ok((&b""[..], a)));
-    assert_eq!(alt3(a), Ok((a, &b""[..])));
-
-    named!(alt4, alt!(tag!("abcd") | tag!("efgh")));
-    let b = &b"efgh"[..];
-    assert_eq!(alt4(a), Ok((&b""[..], a)));
-    assert_eq!(alt4(b), Ok((&b""[..], b)));
-
-    // test the alternative syntax
-    named!(
-      alt5<bool>,
-      alt!(tag!("abcd") => { |_| false } | tag!("efgh") => { |_| true })
-    );
-    assert_eq!(alt5(a), Ok((&b""[..], false)));
-    assert_eq!(alt5(b), Ok((&b""[..], true)));
-
-    // compile-time test guarding against an underspecified E generic type (#474)
-    named!(alt_eof1, alt!(eof!() | eof!()));
-    named!(alt_eof2, alt!(eof!() => {|x| x} | eof!() => {|x| x}));
-    let _ = (alt_eof1, alt_eof2);
-  }
-
-  #[test]
-  fn alt_incomplete() {
-    named!(alt1, alt!(tag!("a") | tag!("bc") | tag!("def")));
-
-    let a = &b""[..];
-    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
-    let a = &b"b"[..];
-    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(2))));
-    let a = &b"bcd"[..];
-    assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..])));
-    let a = &b"cde"[..];
-    assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Alt))));
-    let a = &b"de"[..];
-    assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(3))));
-    let a = &b"defg"[..];
-    assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
-  }
-
-  #[allow(unused_variables)]
-  #[test]
-  fn switch() {
-    named!(
-      sw,
-      switch!(take!(4),
-        b"abcd" | b"xxxx" => take!(2) |
-        b"efgh" => take!(4)
-      )
-    );
-
-    let a = &b"abcdefgh"[..];
-    assert_eq!(sw(a), Ok((&b"gh"[..], &b"ef"[..])));
-
-    let b = &b"efghijkl"[..];
-    assert_eq!(sw(b), Ok((&b""[..], &b"ijkl"[..])));
-    let c = &b"afghijkl"[..];
-    assert_eq!(
-      sw(c),
-      Err(Err::Error(error_position!(
-        &b"afghijkl"[..],
-        ErrorKind::Switch
-      )))
-    );
-
-    let a = &b"xxxxefgh"[..];
-    assert_eq!(sw(a), Ok((&b"gh"[..], &b"ef"[..])));
-  }
-
-  #[test]
-  fn permutation() {
-    named!(
-      perm<(&[u8], &[u8], &[u8])>,
-      permutation!(tag!("abcd"), tag!("efg"), tag!("hi"))
-    );
-
-    let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
-
-    let a = &b"abcdefghijk"[..];
-    assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
-    let b = &b"efgabcdhijk"[..];
-    assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
-    let c = &b"hiefgabcdjk"[..];
-    assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
-
-    let d = &b"efgxyzabcdefghi"[..];
-    assert_eq!(
-      perm(d),
-      Err(Err::Error(error_node_position!(
-        &b"efgxyzabcdefghi"[..],
-        ErrorKind::Permutation,
-        error_position!(&b"xyzabcdefghi"[..], ErrorKind::Permutation)
-      )))
-    );
-
-    let e = &b"efgabc"[..];
-    assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  /*
-  named!(does_not_compile,
-    alt!(tag!("abcd"), tag!("efgh"))
-  );
-  */
-}
diff --git a/src/branch/mod.rs b/src/branch/mod.rs
index 6c0adc7..fcb4df1 100644
--- a/src/branch/mod.rs
+++ b/src/branch/mod.rs
@@ -1,7 +1,36 @@
 //! Choice combinators
 
-#[macro_use]
-mod macros;
+//#[macro_use]
+//mod macros;
+
+#[doc(hidden)]
+#[macro_export(local_inner_macros)]
+macro_rules! succ (
+  (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
+  (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
+  (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
+  (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
+  (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
+  (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
+  (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
+  (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
+  (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
+  (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
+  (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
+  (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
+  (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
+  (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
+  (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
+  (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
+  (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
+  (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
+  (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
+  (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
+  (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
+);
+
+#[cfg(test)]
+mod tests;
 
 use crate::error::ErrorKind;
 use crate::error::ParseError;
diff --git a/src/bytes/macros.rs b/src/bytes/macros.rs
index eedb040..1c1ffc0 100644
--- a/src/bytes/macros.rs
+++ b/src/bytes/macros.rs
@@ -133,30 +133,6 @@ macro_rules! escaped (
 /// * The third argument matches the escaped characters and transforms them
 ///
 /// As an example, the chain `abc\tdef` could be `abc    def` (it also consumes the control character).
-/// # Example
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::character::complete::alpha1;
-/// # use nom::lib::std::str::from_utf8;
-/// # fn main() {
-/// fn to_s(i:Vec<u8>) -> String {
-///   String::from_utf8_lossy(&i).into_owned()
-/// }
-///
-///  named!(transform < String >,
-///    map!(
-///      escaped_transform!(call!(alpha1), '\\',
-///        alt!(
-///            tag!("\\")       => { |_| &b"\\"[..] }
-///          | tag!("\"")       => { |_| &b"\""[..] }
-///          | tag!("n")        => { |_| &b"\n"[..] }
-///        )
-///      ), to_s
-///    )
-///  );
-///  assert_eq!(transform(&b"ab\\\"cd"[..]), Ok((&b""[..], String::from("ab\"cd"))));
-/// # }
-/// ```
 #[cfg(feature = "alloc")]
 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
 #[macro_export(local_inner_macros)]
@@ -436,6 +412,10 @@ macro_rules! take_until1 (
 
 #[cfg(test)]
 mod tests {
+  #[cfg(feature = "alloc")]
+  use crate::bytes::complete::escaped_transform;
+  #[cfg(feature = "alloc")]
+  use crate::bytes::complete::tag;
   use crate::character::is_alphabetic;
   use crate::character::streaming::{
     alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
@@ -444,6 +424,10 @@ mod tests {
   use crate::error::ErrorKind;
   use crate::internal::{Err, IResult, Needed};
   #[cfg(feature = "alloc")]
+  use crate::branch::alt;
+  #[cfg(feature = "alloc")]
+  use crate::combinator::{map, value};
+  #[cfg(feature = "alloc")]
   use crate::lib::std::string::String;
   #[cfg(feature = "alloc")]
   use crate::lib::std::vec::Vec;
@@ -580,23 +564,16 @@ mod tests {
   #[cfg(feature = "alloc")]
   #[test]
   fn escape_transform() {
-    use crate::lib::std::str;
-
-    named!(
-      esc<String>,
-      map!(
-        escaped_transform!(
-          alpha,
-          '\\',
-          alt!(
-              tag!("\\")       => { |_| &b"\\"[..] }
-            | tag!("\"")       => { |_| &b"\""[..] }
-            | tag!("n")        => { |_| &b"\n"[..] }
-          )
-        ),
-        to_s
-      )
-    );
+    fn esc(i: &[u8]) -> IResult<&[u8], String> {
+        map(
+            escaped_transform(alpha, '\\',
+                          alt((
+                            value(&b"\\"[..], tag("\\")),
+                            value(&b"\""[..], tag("\"")),
+                            value(&b"\n"[..], tag("n")),
+                          ))),
+            to_s)(i)
+    }
 
     assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
     assert_eq!(
@@ -624,24 +601,19 @@ mod tests {
       Err(Err::Error(error_node_position!(
         &b"AB\\A"[..],
         ErrorKind::EscapedTransform,
-        error_position!(&b"A"[..], ErrorKind::Alt)
+        error_position!(&b"A"[..], ErrorKind::Tag)
       )))
     );
 
-    named!(
-      esc2<String>,
-      map!(
-        escaped_transform!(
-          call!(alpha),
-          '&',
-          alt!(
-              tag!("egrave;") => { |_| str::as_bytes("è") }
-            | tag!("agrave;") => { |_| str::as_bytes("à") }
-          )
-        ),
-        to_s
-      )
-    );
+    fn esc2(i: &[u8]) -> IResult<&[u8], String> {
+        map(
+            escaped_transform(alpha, '&',
+                          alt((
+                            value("è".as_bytes(), tag("egrave;")),
+                            value("à".as_bytes(), tag("agrave;"))
+                          ))),
+            to_s)(i)
+    }
     assert_eq!(
       esc2(&b"ab&egrave;DEF;"[..]),
       Ok((&b";"[..], String::from("abèDEF")))
@@ -655,13 +627,14 @@ mod tests {
   #[cfg(feature = "std")]
   #[test]
   fn escape_transform_str() {
-    named!(esc<&str, String>, escaped_transform!(alpha, '\\',
-      alt!(
-          tag!("\\")       => { |_| "\\" }
-        | tag!("\"")       => { |_| "\"" }
-        | tag!("n")        => { |_| "\n" }
-      ))
-    );
+    fn esc(i: &str) -> IResult<&str, String> {
+        escaped_transform(alpha, '\\',
+                          alt((
+                            value("\\", tag("\\")),
+                            value("\"", tag("\"")),
+                            value("\n", tag("n")),
+                          )))(i)
+    }
 
     assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
     assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
@@ -680,26 +653,30 @@ mod tests {
       Err(Err::Error(error_node_position!(
         "AB\\A",
         ErrorKind::EscapedTransform,
-        error_position!("A", ErrorKind::Alt)
+        error_position!("A", ErrorKind::Tag)
       )))
     );
 
-    named!(esc2<&str, String>, escaped_transform!(alpha, '&',
-      alt!(
-          tag!("egrave;") => { |_| "è" }
-        | tag!("agrave;") => { |_| "à" }
-      ))
-    );
+    fn esc2(i: &str) -> IResult<&str, String> {
+        escaped_transform(alpha, '&',
+                          alt((
+                            value("è", tag("egrave;")),
+                            value("à", tag("agrave;"))
+                          )))(i)
+    }
     assert_eq!(esc2("ab&egrave;DEF;"), Ok((";", String::from("abèDEF"))));
     assert_eq!(
       esc2("ab&egrave;D&agrave;EF;"),
       Ok((";", String::from("abèDàEF")))
     );
 
-    named!(esc3<&str, String>, escaped_transform!(alpha, '␛',
-      alt!(
-        tag!("0") => { |_| "\0" } |
-        tag!("n") => { |_| "\n" })));
+    fn esc3(i: &str) -> IResult<&str, String> {
+        escaped_transform(alpha, '␛',
+                          alt((
+                            value("\0", tag("0")),
+                            value("\n", tag("n"))
+                          )))(i)
+    }
     assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
   }
 
@@ -937,14 +914,24 @@ mod tests {
 
   #[test]
   fn length_bytes() {
-    use crate::number::streaming::le_u8;
-    named!(x, length_data!(le_u8));
+    use crate::{
+        number::streaming::le_u8,
+        bytes::streaming::tag,
+        multi::length_data
+    };
+
+    fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
+        length_data(le_u8)(i)
+    }
     assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..])));
     assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..])));
     assert_eq!(x(b"\x02."), Err(Err::Incomplete(Needed::new(1))));
     assert_eq!(x(b"\x02"), Err(Err::Incomplete(Needed::new(2))));
 
-    named!(y, do_parse!(tag!("magic") >> b: length_data!(le_u8) >> (b)));
+    fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
+        let (i, _) = tag("magic")(i)?;
+        length_data(le_u8)(i)
+    }
     assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..])));
     assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..])));
     assert_eq!(y(b"magic\x02."), Err(Err::Incomplete(Needed::new(1))));
diff --git a/src/character/complete.rs b/src/character/complete.rs
index cbcff46..6e255f6 100644
--- a/src/character/complete.rs
+++ b/src/character/complete.rs
@@ -936,12 +936,10 @@ mod tests {
 
   #[test]
   fn full_line_windows() {
-    //let not_line_ending = |i:&[u8]| take_while(|c| c != b'\r' && c != b'\n')(i);
-
-    named!(
-      take_full_line<(&[u8], &[u8])>,
-      tuple!(not_line_ending, line_ending)
-    );
+    use crate::sequence::pair;
+    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+      pair(not_line_ending, line_ending)(i)
+    }
     let input = b"abc\r\n";
     let output = take_full_line(input);
     assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
@@ -949,11 +947,10 @@ mod tests {
 
   #[test]
   fn full_line_unix() {
-    //let not_line_ending = |i:&[u8]| take_while(|c| c != b'\n')(i);
-    named!(
-      take_full_line<(&[u8], &[u8])>,
-      tuple!(not_line_ending, line_ending)
-    );
+    use crate::sequence::pair;
+    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+      pair(not_line_ending, line_ending)(i)
+    }
     let input = b"abc\n";
     let output = take_full_line(input);
     assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
diff --git a/src/character/streaming.rs b/src/character/streaming.rs
index 4c33ee9..af232d4 100644
--- a/src/character/streaming.rs
+++ b/src/character/streaming.rs
@@ -614,6 +614,7 @@ mod tests {
   use super::*;
   use crate::error::ErrorKind;
   use crate::internal::{Err, Needed};
+  use crate::sequence::pair;
 
   macro_rules! assert_parse(
     ($left: expr, $right: expr) => {
@@ -920,10 +921,9 @@ mod tests {
 
   #[test]
   fn full_line_windows() {
-    named!(
-      take_full_line<(&[u8], &[u8])>,
-      tuple!(not_line_ending, line_ending)
-    );
+    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+      pair(not_line_ending, line_ending)(i)
+    }
     let input = b"abc\r\n";
     let output = take_full_line(input);
     assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
@@ -931,10 +931,9 @@ mod tests {
 
   #[test]
   fn full_line_unix() {
-    named!(
-      take_full_line<(&[u8], &[u8])>,
-      tuple!(not_line_ending, line_ending)
-    );
+    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+      pair(not_line_ending, line_ending)(i)
+    }
     let input = b"abc\n";
     let output = take_full_line(input);
     assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
diff --git a/src/combinator/macros.rs b/src/combinator/macros.rs
index 11ece16..b66d519 100644
--- a/src/combinator/macros.rs
+++ b/src/combinator/macros.rs
@@ -131,67 +131,6 @@ macro_rules! named (
     );
 );
 
-/// Makes a function from a parser combination with arguments.
-///
-/// ```ignore
-/// //takes [`&[u8]`] as input
-/// named_args!(tagged(open_tag: &[u8], close_tag: &[u8])<&str>,
-///   delimited!(tag!(open_tag), map_res!(take!(4), str::from_utf8), tag!(close_tag))
-/// );
-
-/// //takes `&str` as input
-/// named_args!(tagged(open_tag: &str, close_tag: &str)<&str, &str>,
-///   delimited!(tag!(open_tag), take!(4), tag!(close_tag))
-/// );
-/// ```
-///
-/// Note: If using arguments that way gets hard to read, it is always
-/// possible to write the equivalent parser definition manually, like
-/// this:
-///
-/// ```ignore
-/// fn tagged(input: &[u8], open_tag: &[u8], close_tag: &[u8]) -> IResult<&[u8], &str> {
-///   // the first combinator in the tree gets the input as argument. It is then
-///   // passed from one combinator to the next through macro rewriting
-///   delimited!(input,
-///     tag!(open_tag), take!(4), tag!(close_tag)
-///   )
-/// );
-/// ```
-///
-#[macro_export(local_inner_macros)]
-macro_rules! named_args {
-    ($vis:vis $func_name:ident ( $( $arg:ident : $typ:ty ),* ) < $return_type:ty > , $submac:ident!( $($args:tt)* ) ) => {
-        $vis fn $func_name(input: &[u8], $( $arg : $typ ),*) -> $crate::IResult<&[u8], $return_type> {
-            $submac!(input, $($args)*)
-        }
-    };
-
-    ($vis:vis $func_name:ident < 'a > ( $( $arg:ident : $typ:ty ),* ) < $return_type:ty > , $submac:ident!( $($args:tt)* ) ) => {
-        $vis fn $func_name<'this_is_probably_unique_i_hope_please, 'a>(
-          input: &'this_is_probably_unique_i_hope_please [u8], $( $arg : $typ ),*) ->
-          $crate::IResult<&'this_is_probably_unique_i_hope_please [u8], $return_type>
-        {
-          $submac!(input, $($args)*)
-        }
-    };
-
-    ($vis:vis $func_name:ident ( $( $arg:ident : $typ:ty ),* ) < $input_type:ty, $return_type:ty > , $submac:ident!( $($args:tt)* ) ) => {
-        $vis fn $func_name(input: $input_type, $( $arg : $typ ),*) -> $crate::IResult<$input_type, $return_type> {
-            $submac!(input, $($args)*)
-        }
-    };
-
-    ($vis:vis $func_name:ident < 'a > ( $( $arg:ident : $typ:ty ),* ) < $input_type:ty, $return_type:ty > , $submac:ident!( $($args:tt)* ) ) => {
-        $vis fn $func_name<'a>(
-          input: $input_type, $( $arg : $typ ),*)
-          -> $crate::IResult<$input_type, $return_type>
-        {
-            $submac!(input, $($args)*)
-        }
-    };
-}
-
 /// Makes a function from a parser combination, with attributes.
 ///
 /// The usage of this macro is almost identical to `named!`, except that
@@ -282,38 +221,6 @@ macro_rules! call (
 /// Additionally, the error chain contains number identifiers
 /// that can be matched to provide useful error messages.
 ///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///     named!(err_test<&[u8], &[u8]>, alt!(
-///       tag!("abcd") |
-///       preceded!(tag!("efgh"), return_error!(ErrorKind::Eof,
-///           do_parse!(
-///                  tag!("ijkl")                                        >>
-///             res: return_error!(ErrorKind::Tag, tag!("mnop")) >>
-///             (res)
-///           )
-///         )
-///       )
-///     ));
-///     let a = &b"efghblah"[..];
-///     let b = &b"efghijklblah"[..];
-///     let c = &b"efghijklmnop"[..];
-///
-///     let blah = &b"blah"[..];
-///
-///     let res_a = err_test(a);
-///     let res_b = err_test(b);
-///     let res_c = err_test(c);
-///     assert_eq!(res_a, Err(Err::Failure(error_node_position!(blah, ErrorKind::Eof, error_position!(blah, ErrorKind::Tag)))));
-///     assert_eq!(res_b, Err(Err::Failure(error_node_position!(&b"ijklblah"[..], ErrorKind::Eof,
-///       error_node_position!(blah, ErrorKind::Tag, error_position!(blah, ErrorKind::Tag))))
-///     ));
-/// # }
-/// ```
-///
 #[macro_export(local_inner_macros)]
 macro_rules! return_error (
   ($i:expr, $code:expr, $submac:ident!( $($args:tt)* )) => (
diff --git a/src/multi/macros.rs b/src/multi/macros.rs
deleted file mode 100644
index c03de3a..0000000
--- a/src/multi/macros.rs
+++ /dev/null
@@ -1,1079 +0,0 @@
-//! Parsers for applying parsers multiple times
-
-/// `separated_list0!(I -> IResult<I,T>, I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// `separated_list0(sep, X)` returns a `Vec<X>`.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, error::ErrorKind, Needed, IResult};
-/// use nom::multi::separated_list0;
-/// use nom::bytes::complete::tag;
-///
-/// # fn main() {
-/// named!(parser<&str, Vec<&str>>, separated_list0!(tag("|"), tag("abc")));
-///
-/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
-/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
-/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
-/// assert_eq!(parser(""), Ok(("", vec![])));
-/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![])));
-/// # }
-/// ```
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! separated_list0(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
-    separated_list0!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
-  );
-
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    separated_list0!($i, |i| $submac!(i, $($args)*), $g);
-  );
-
-  ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    separated_list0!($i, $f, |i| $submac!(i, $($args)*));
-  );
-
-  ($i:expr, $f:expr, $g:expr) => (
-    $crate::multi::separated_list0c($i, $f, $g)
-  );
-);
-
-/// `separated_list1!(I -> IResult<I,T>, I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// `separated_list1(sep, X)` returns a `Vec<X>`.
-///
-/// It will return an error if there is no element in the list.
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
-/// use nom::multi::separated_list1;
-/// use nom::bytes::complete::tag;
-///
-/// # fn main() {
-/// named!(parser<&str, Vec<&str>>, separated_list1!(tag("|"), tag("abc")));
-///
-/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
-/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
-/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
-/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
-/// assert_eq!(parser("def|abc"), Err(Err::Error(Error::new("def|abc", ErrorKind::Tag))));
-/// # }
-/// ```
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! separated_list1(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
-    separated_list1!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
-  );
-
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    separated_list1!($i, |i| $submac!(i, $($args)*), $g);
-  );
-
-  ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    separated_list1!($i, $f, |i| $submac!(i, $($args)*));
-  );
-
-  ($i:expr, $f:expr, $g:expr) => (
-    $crate::multi::separated_list1c($i, $f, $g)
-  );
-);
-
-/// `many0!(I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// Applies the parser 0 or more times and returns the list of results in a `Vec`.
-///
-/// The embedded parser may return `Incomplete`.
-///
-/// `many0` will only return `Error` if the embedded parser does not consume any input
-/// (to avoid infinite loops).
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >, many0!( tag!( "abcd" ) ) );
-///
-///  let a = b"abcdabcdefgh";
-///  let b = b"azerty";
-///
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&a[..]),Ok((&b"efgh"[..], res)));
-///  assert_eq!(multi(&b[..]),Ok((&b"azerty"[..], Vec::new())));
-/// # }
-/// ```
-///
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! many0(
-  ($i:expr, $submac:ident!( $($args:tt)* )) => (
-    many0!($i, |i| $submac!(i, $($args)*))
-  );
-  ($i:expr, $f:expr) => (
-    $crate::multi::many0c($i, $f)
-  );
-);
-
-/// `many1!(I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// Applies the parser 1 or more times and returns the list of results in a `Vec`.
-///
-/// The embedded parser may return `Incomplete`.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >, many1!( tag!( "abcd" ) ) );
-///
-///  let a = b"abcdabcdefgh";
-///  let b = b"azerty";
-///
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&a[..]), Ok((&b"efgh"[..], res)));
-///  assert_eq!(multi(&b[..]), Err(Err::Error(error_position!(&b[..], ErrorKind::Tag))));
-/// # }
-/// ```
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! many1(
-  ($i:expr, $submac:ident!( $($args:tt)* )) => (
-    many1!($i, |i| $submac!(i, $($args)*))
-  );
-  ($i:expr, $f:expr) => (
-    $crate::multi::many1c($i, $f)
-  );
-);
-
-/// `many_till!(I -> IResult<I,O>, I -> IResult<I,P>) => I -> IResult<I, (Vec<O>, P)>`
-/// Applies the first parser until the second applies. Returns a tuple containing the list
-/// of results from the first in a Vec and the result of the second.
-///
-/// The first embedded parser may return `Incomplete`.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///    named!(multi<&[u8], (Vec<&[u8]>, &[u8]) >, many_till!( tag!( "abcd" ), tag!( "efgh" ) ) );
-///
-///    let a = b"abcdabcdefghabcd";
-///    let b = b"efghabcd";
-///    let c = b"azerty";
-///
-///    let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]);
-///    let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]);
-///    assert_eq!(multi(&a[..]),Ok((&b"abcd"[..], res_a)));
-///    assert_eq!(multi(&b[..]),Ok((&b"abcd"[..], res_b)));
-///    assert_eq!(multi(&c[..]), Err(Err::Error(error_node_position!(&c[..], ErrorKind::ManyTill,
-///      error_position!(&c[..], ErrorKind::Tag)))));
-/// # }
-/// ```
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! many_till(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
-    many_till!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
-  );
-
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    many_till!($i, |i| $submac!(i, $($args)*), $g);
-  );
-
-  ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    many_till!($i, $f, |i| $submac!(i, $($args)*));
-  );
-
-  ($i:expr, $f:expr, $g:expr) => (
-    $crate::multi::many_tillc($i, $f, $g)
-  );
-);
-
-/// `many_m_n!(usize, usize, I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// Applies the parser between m and n times (n included) and returns the list of
-/// results in a `Vec`.
-///
-/// the embedded parser may return Incomplete
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >, many_m_n!(2, 4, tag!( "abcd" ) ) );
-///
-///  let a = b"abcdefgh";
-///  let b = b"abcdabcdefgh";
-///  let c = b"abcdabcdabcdabcdabcdefgh";
-///
-///  assert_eq!(multi(&a[..]), Err(Err::Error(error_position!(&b"efgh"[..], ErrorKind::Tag))));
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&b[..]),Ok((&b"efgh"[..], res)));
-///  let res2 = vec![&b"abcd"[..], &b"abcd"[..], &b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&c[..]),Ok((&b"abcdefgh"[..], res2)));
-/// # }
-/// ```
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! many_m_n(
-  ($i:expr, $m:expr, $n: expr, $submac:ident!( $($args:tt)* )) => (
-    many_m_n!($i, $m, $n, |i| $submac!(i, $($args)*))
-  );
-  ($i:expr, $m:expr, $n: expr, $f:expr) => (
-    $crate::multi::many_m_nc($i, $m, $n, $f)
-  );
-);
-
-/// `many0_count!(I -> IResult<I,O>) => I -> IResult<I, usize>`
-/// Applies the parser 0 or more times and returns the number of times the parser was applied.
-///
-/// `many0_count` will only return `Error` if the embedded parser does not consume any input
-/// (to avoid infinite loops).
-///
-/// ```
-/// #[macro_use] extern crate nom;
-/// use nom::character::streaming::digit1;
-///
-/// named!(number<&[u8], usize>, many0_count!(pair!(digit1, tag!(","))));
-///
-/// fn main() {
-///     assert_eq!(number(&b"123,45,abc"[..]), Ok((&b"abc"[..], 2)));
-/// }
-/// ```
-///
-#[macro_export]
-macro_rules! many0_count {
-  ($i:expr, $submac:ident!( $($args:tt)* )) => (
-    $crate::multi::many0_countc($i, |i| $submac!(i, $($args)*))
-  );
-
-  ($i:expr, $f:expr) => (
-    $crate::multi::many0_countc($i, $f)
-  );
-}
-
-/// `many1_count!(I -> IResult<I,O>) => I -> IResult<I, usize>`
-/// Applies the parser 1 or more times and returns the number of times the parser was applied.
-///
-/// ```
-/// #[macro_use] extern crate nom;
-/// use nom::character::streaming::digit1;
-///
-/// named!(number<&[u8], usize>, many1_count!(pair!(digit1, tag!(","))));
-///
-/// fn main() {
-///     assert_eq!(number(&b"123,45,abc"[..]), Ok((&b"abc"[..], 2)));
-/// }
-/// ```
-///
-#[macro_export]
-macro_rules! many1_count {
-  ($i:expr, $submac:ident!( $($args:tt)* )) => (
-    $crate::multi::many1_countc($i, |i| $submac!(i, $($args)*))
-  );
-
-  ($i:expr, $f:expr) => (
-    $crate::multi::many1_countc($i, $f)
-  );
-}
-
-/// `count!(I -> IResult<I,O>, nb) => I -> IResult<I, Vec<O>>`
-/// Applies the child parser a specified number of times.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(counter< Vec<&[u8]> >, count!( tag!( "abcd" ), 2 ) );
-///
-///  let a = b"abcdabcdabcdef";
-///  let b = b"abcdefgh";
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///
-///  assert_eq!(counter(&a[..]),Ok((&b"abcdef"[..], res)));
-///  assert_eq!(counter(&b[..]), Err(Err::Error(error_position!(&b"efgh"[..], ErrorKind::Tag))));
-/// # }
-/// ```
-///
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-#[macro_export(local_inner_macros)]
-macro_rules! count(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $count: expr) => (
-    count!($i, |i| $submac!(i, $($args)*), $count)
-  );
-  ($i:expr, $f:expr, $count: expr) => (
-    $crate::multi::count($f, $count)($i)
-  );
-);
-
-/// `length_count!(I -> IResult<I, nb>, I -> IResult<I,O>) => I -> IResult<I, Vec<O>>`
-/// Gets a number from the first parser, then applies the second parser that many times.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// # use nom::error::ErrorKind;
-/// use nom::number::complete::be_u8;
-/// # fn main() {
-/// named!(parser<Vec<&[u8]>>, length_count!(be_u8, tag!("abc")));
-///
-/// assert_eq!(parser(&b"\x02abcabcabc"[..]), Ok(((&b"abc"[..], vec![&b"abc"[..], &b"abc"[..]]))));
-/// assert_eq!(parser(&b"\x04abcabcabc"[..]), Err(Err::Incomplete(Needed::new(3))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-#[cfg(feature = "alloc")]
-#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
-macro_rules! length_count(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
-    {
-      use $crate::lib::std::result::Result::*;
-      use $crate::Err;
-
-      match $submac!($i, $($args)*) {
-        Err(e)     => Err(Err::convert(e)),
-        Ok((i, o)) => {
-          match count!(i, $submac2!($($args2)*), o as usize) {
-            Err(e)       => Err(Err::convert(e)),
-            Ok((i2, o2)) => Ok((i2, o2))
-          }
-        }
-      }
-    }
-  );
-
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    length_count!($i, $submac!($($args)*), call!($g));
-  );
-
-  ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    length_count!($i, call!($f), $submac!($($args)*));
-  );
-
-  ($i:expr, $f:expr, $g:expr) => (
-    length_count!($i, call!($f), call!($g));
-  );
-);
-
-/// `length_data!(I -> IResult<I, nb>) => O`
-///
-/// `length_data` gets a number from the first parser, then takes a subslice of the input
-/// of that size and returns that subslice.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// # use nom::error::ErrorKind;
-/// use nom::number::complete::be_u8;
-/// # fn main() {
-/// named!(parser, length_data!(be_u8));
-///
-/// assert_eq!(parser(&b"\x06abcabcabc"[..]), Ok((&b"abc"[..], &b"abcabc"[..])));
-/// assert_eq!(parser(&b"\x06abc"[..]), Err(Err::Incomplete(Needed::new(3))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! length_data(
-  ($i:expr, $submac:ident!( $($args:tt)* )) => ({
-    $crate::multi::length_data(|i| $submac!(i, $($args)*))($i)
-  });
-
-  ($i:expr, $f:expr) => (
-    $crate::multi::length_data($f)($i)
-  );
-);
-
-/// `length_value!(I -> IResult<I, nb>, I -> IResult<I,O>) => I -> IResult<I, O>`
-///
-/// Gets a number from the first parser, takes a subslice of the input of that size,
-/// then applies the second parser on that subslice. If the second parser returns
-/// `Incomplete`, `length_value` will return an error.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// # use nom::error::ErrorKind;
-/// use nom::number::complete::be_u8;
-/// use nom::character::complete::alpha0;
-/// use nom::bytes::complete::tag;
-/// # fn main() {
-/// named!(parser, length_value!(be_u8, alpha0));
-///
-/// assert_eq!(parser(&b"\x06abcabcabc"[..]), Ok((&b"abc"[..], &b"abcabc"[..])));
-/// assert_eq!(parser(&b"\x06abc"[..]), Err(Err::Incomplete(Needed::new(3))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! length_value(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
-    length_value!($i, |i| $submac!(i, $($args)*), |i| $submac2!(i, $($args2)*))
-  );
-
-  ($i:expr, $submac:ident!( $($args:tt)* ), $g:expr) => (
-    length_value!($i, |i| $submac!(i, $($args)*), $g);
-  );
-
-  ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    length_value!($i, $f, |i| $submac!(i, $($args)*));
-  );
-
-  ($i:expr, $f:expr, $g:expr) => (
-    $crate::multi::length_valuec($i, $f, $g);
-  );
-);
-
-/// `fold_many0!(I -> IResult<I,O>, R, Fn(R, O) -> R) => I -> IResult<I, R>`
-/// Applies the parser 0 or more times and folds the list of return values.
-///
-/// The embedded parser may return `Incomplete`.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >,
-///    fold_many0!( tag!( "abcd" ), Vec::new(), |mut acc: Vec<_>, item| {
-///      acc.push(item);
-///      acc
-///  }));
-///
-///  let a = b"abcdabcdefgh";
-///  let b = b"azerty";
-///
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&a[..]),Ok((&b"efgh"[..], res)));
-///  assert_eq!(multi(&b[..]),Ok((&b"azerty"[..], Vec::new())));
-/// # }
-/// ```
-/// 0 or more
-#[macro_export(local_inner_macros)]
-macro_rules! fold_many0(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $init:expr, $fold_f:expr) => (
-    fold_many0!($i, |i| $submac!(i, $($args)*), $init, $fold_f)
-  );
-  ($i:expr, $f:expr, $init:expr, $fold_f:expr) => (
-    $crate::multi::fold_many0c($i, $f, $init, $fold_f)
-  );
-);
-
-/// `fold_many1!(I -> IResult<I,O>, R, Fn(R, O) -> R) => I -> IResult<I, R>`
-/// Applies the parser 1 or more times and folds the list of return values.
-///
-/// The embedded parser may return `Incomplete`.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >,
-///    fold_many1!( tag!( "abcd" ), Vec::new(), |mut acc: Vec<_>, item| {
-///      acc.push(item);
-///      acc
-///  }));
-///
-///  let a = b"abcdabcdefgh";
-///  let b = b"azerty";
-///
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&a[..]),Ok((&b"efgh"[..], res)));
-///  assert_eq!(multi(&b[..]), Err(Err::Error(error_position!(&b[..], ErrorKind::Many1))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! fold_many1(
-  ($i:expr, $submac:ident!( $($args:tt)* ), $init:expr, $fold_f:expr) => (
-    fold_many1!($i, |i| $submac!(i, $($args)*), $init, $fold_f)
-  );
-  ($i:expr, $f:expr, $init:expr, $fold_f:expr) => (
-    $crate::multi::fold_many1c($i, $f, $init, $fold_f)
-  );
-  ($i:expr, $f:expr, $init:expr, $fold_f:expr) => (
-    fold_many1!($i, call!($f), $init, $fold_f);
-  );
-);
-
-/// `fold_many_m_n!(usize, usize, I -> IResult<I,O>, R, Fn(R, O) -> R) => I -> IResult<I, R>`
-/// Applies the parser between m and n times (n included) and folds the list of return value.
-///
-/// The embedded parser may return `Incomplete`.
-///
-/// ```
-/// # #[macro_use] extern crate nom;
-/// # use nom::Err;
-/// # use nom::error::ErrorKind;
-/// # fn main() {
-///  named!(multi<&[u8], Vec<&[u8]> >,
-///    fold_many_m_n!(2, 4, tag!( "abcd" ), Vec::new(), |mut acc: Vec<_>, item| {
-///      acc.push(item);
-///      acc
-///  }));
-///
-///  let a = b"abcdefgh";
-///  let b = b"abcdabcdefgh";
-///  let c = b"abcdabcdabcdabcdabcdefgh";
-///
-///  assert_eq!(multi(&a[..]), Err(Err::Error(error_position!(&b"efgh"[..], ErrorKind::Tag))));
-///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&b[..]),Ok((&b"efgh"[..], res)));
-///  let res2 = vec![&b"abcd"[..], &b"abcd"[..], &b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&c[..]),Ok((&b"abcdefgh"[..], res2)));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! fold_many_m_n(
-  ($i:expr, $m:expr, $n:expr, $submac:ident!( $($args:tt)* ), $init:expr, $fold_f:expr) => (
-    fold_many_m_n!($i, $m, $n, |i| $submac!(i, $($args)*), $init, $fold_f)
-  );
-  ($i:expr, $m:expr, $n:expr, $f:expr, $init:expr, $fold_f:expr) => (
-    $crate::multi::fold_many_m_nc($i, $m, $n, $f, $init, $fold_f)
-  );
-);
-
-#[cfg(test)]
-mod tests {
-  use crate::character::streaming::digit1 as digit;
-  use crate::error::ErrorKind;
-  use crate::error::ParseError;
-  use crate::internal::{Err, IResult, Needed};
-  use crate::lib::std::str::{self, FromStr};
-  #[cfg(feature = "alloc")]
-  use crate::lib::std::vec::Vec;
-  use crate::number::streaming::{be_u16, be_u8};
-
-  // reproduce the tag and take macros, because of module import order
-  macro_rules! tag (
-    ($i:expr, $inp: expr) => (
-      {
-        #[inline(always)]
-        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
-          b.as_bytes()
-        }
-
-        let expected = $inp;
-        let bytes    = as_bytes(&expected);
-
-        tag_bytes!($i,bytes)
-      }
-    );
-  );
-
-  macro_rules! tag_bytes (
-    ($i:expr, $bytes: expr) => (
-      {
-        use $crate::lib::std::cmp::min;
-        let len = $i.len();
-        let blen = $bytes.len();
-        let m   = min(len, blen);
-        let reduced = &$i[..m];
-        let b       = &$bytes[..m];
-
-        let res: IResult<_,_,_> = if reduced != b {
-          Err($crate::Err::Error($crate::error::make_error($i, $crate::error::ErrorKind::Tag)))
-        } else if m < blen {
-          Err($crate::Err::Incomplete(Needed::new(blen)))
-        } else {
-          Ok((&$i[blen..], reduced))
-        };
-        res
-      }
-    );
-  );
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn separated_list0() {
-    named!(multi<&[u8],Vec<&[u8]> >, separated_list0!(tag!(","), tag!("abcd")));
-    named!(multi_empty<&[u8],Vec<&[u8]> >, separated_list0!(tag!(","), tag!("")));
-    named!(empty_sep<&[u8],Vec<&[u8]> >, separated_list0!(tag!(""), tag!("abc")));
-    named!(multi_longsep<&[u8],Vec<&[u8]> >, separated_list0!(tag!(".."), tag!("abcd")));
-
-    let a = &b"abcdef"[..];
-    let b = &b"abcd,abcdef"[..];
-    let c = &b"azerty"[..];
-    let d = &b",,abc"[..];
-    let e = &b"abcd,abcd,ef"[..];
-    let f = &b"abc"[..];
-    let g = &b"abcd."[..];
-    let h = &b"abcd,abc"[..];
-    let i = &b"abcabc"[..];
-
-    let res1 = vec![&b"abcd"[..]];
-    assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
-    let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
-    assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new())));
-    let res3 = vec![&b""[..], &b""[..], &b""[..]];
-    assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3)));
-    let i_err_pos = &i[3..];
-    assert_eq!(
-      empty_sep(i),
-      Err(Err::Error(error_position!(
-        i_err_pos,
-        ErrorKind::SeparatedList
-      )))
-    );
-    let res4 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(e), Ok((&b",ef"[..], res4)));
-
-    assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(2))));
-    assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn separated_list1() {
-    named!(multi<&[u8],Vec<&[u8]> >, separated_list1!(tag!(","), tag!("abcd")));
-    named!(multi_longsep<&[u8],Vec<&[u8]> >, separated_list1!(tag!(".."), tag!("abcd")));
-
-    let a = &b"abcdef"[..];
-    let b = &b"abcd,abcdef"[..];
-    let c = &b"azerty"[..];
-    let d = &b"abcd,abcd,ef"[..];
-
-    let f = &b"abc"[..];
-    let g = &b"abcd."[..];
-    let h = &b"abcd,abc"[..];
-
-    let res1 = vec![&b"abcd"[..]];
-    assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
-    let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
-    assert_eq!(
-      multi(c),
-      Err(Err::Error(error_position!(c, ErrorKind::Tag)))
-    );
-    let res3 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(d), Ok((&b",ef"[..], res3)));
-
-    assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(2))));
-    assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn many0() {
-    named!(tag_abcd, tag!("abcd"));
-    named!(tag_empty, tag!(""));
-    named!( multi<&[u8],Vec<&[u8]> >, many0!(tag_abcd) );
-    named!( multi_empty<&[u8],Vec<&[u8]> >, many0!(tag_empty) );
-
-    assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
-    assert_eq!(
-      multi(&b"abcdabcdefgh"[..]),
-      Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
-    );
-    assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
-    assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(
-      multi_empty(&b"abcdef"[..]),
-      Err(Err::Error(error_position!(
-        &b"abcdef"[..],
-        ErrorKind::Many0
-      )))
-    );
-  }
-
-  #[cfg(nightly)]
-  use test::Bencher;
-
-  #[cfg(nightly)]
-  #[bench]
-  fn many0_bench(b: &mut Bencher) {
-    named!(multi<&[u8],Vec<&[u8]> >, many0!(tag!("abcd")));
-    b.iter(|| multi(&b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"[..]));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn many1() {
-    named!(multi<&[u8],Vec<&[u8]> >, many1!(tag!("abcd")));
-
-    let a = &b"abcdef"[..];
-    let b = &b"abcdabcdefgh"[..];
-    let c = &b"azerty"[..];
-    let d = &b"abcdab"[..];
-
-    let res1 = vec![&b"abcd"[..]];
-    assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
-    let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
-    assert_eq!(
-      multi(c),
-      Err(Err::Error(error_position!(c, ErrorKind::Tag)))
-    );
-    assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn many_till() {
-    named!(multi<&[u8], (Vec<&[u8]>, &[u8]) >, many_till!( tag!( "abcd" ), tag!( "efgh" ) ) );
-
-    let a = b"abcdabcdefghabcd";
-    let b = b"efghabcd";
-    let c = b"azerty";
-
-    let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]);
-    let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]);
-    assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a)));
-    assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b)));
-    assert_eq!(
-      multi(&c[..]),
-      Err(Err::Error(error_node_position!(
-        &c[..],
-        ErrorKind::ManyTill,
-        error_position!(&c[..], ErrorKind::Tag)
-      )))
-    );
-  }
-
-  #[test]
-  #[cfg(feature = "std")]
-  fn infinite_many() {
-    fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
-      println!("input: {:?}", input);
-      Err(Err::Error(error_position!(input, ErrorKind::Tag)))
-    }
-
-    // should not go into an infinite loop
-    named!(multi0<&[u8],Vec<&[u8]> >, many0!(tst));
-    let a = &b"abcdef"[..];
-    assert_eq!(multi0(a), Ok((a, Vec::new())));
-
-    named!(multi1<&[u8],Vec<&[u8]> >, many1!(tst));
-    let a = &b"abcdef"[..];
-    assert_eq!(
-      multi1(a),
-      Err(Err::Error(error_position!(a, ErrorKind::Tag)))
-    );
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn many_m_n() {
-    named!(multi<&[u8],Vec<&[u8]> >, many_m_n!(2, 4, tag!("Abcd")));
-
-    let a = &b"Abcdef"[..];
-    let b = &b"AbcdAbcdefgh"[..];
-    let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
-    let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
-    let e = &b"AbcdAb"[..];
-
-    assert_eq!(
-      multi(a),
-      Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
-    );
-    let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
-    let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
-    let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
-    assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn count() {
-    const TIMES: usize = 2;
-    named!(tag_abc, tag!("abc"));
-    named!( cnt_2<&[u8], Vec<&[u8]> >, count!(tag_abc, TIMES ) );
-
-    assert_eq!(
-      cnt_2(&b"abcabcabcdef"[..]),
-      Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
-    );
-    assert_eq!(cnt_2(&b"ab"[..]), Err(Err::Incomplete(Needed::new(3))));
-    assert_eq!(cnt_2(&b"abcab"[..]), Err(Err::Incomplete(Needed::new(3))));
-    assert_eq!(
-      cnt_2(&b"xxx"[..]),
-      Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
-    );
-    assert_eq!(
-      cnt_2(&b"xxxabcabcdef"[..]),
-      Err(Err::Error(error_position!(
-        &b"xxxabcabcdef"[..],
-        ErrorKind::Tag
-      )))
-    );
-    assert_eq!(
-      cnt_2(&b"abcxxxabcdef"[..]),
-      Err(Err::Error(error_position!(
-        &b"xxxabcdef"[..],
-        ErrorKind::Tag
-      )))
-    );
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn count_zero() {
-    const TIMES: usize = 0;
-    named!(tag_abc, tag!("abc"));
-    named!( counter_2<&[u8], Vec<&[u8]> >, count!(tag_abc, TIMES ) );
-
-    let done = &b"abcabcabcdef"[..];
-    let parsed_done = Vec::new();
-    let rest = done;
-    let incomplete_1 = &b"ab"[..];
-    let parsed_incompl_1 = Vec::new();
-    let incomplete_2 = &b"abcab"[..];
-    let parsed_incompl_2 = Vec::new();
-    let error = &b"xxx"[..];
-    let error_remain = &b"xxx"[..];
-    let parsed_err = Vec::new();
-    let error_1 = &b"xxxabcabcdef"[..];
-    let parsed_err_1 = Vec::new();
-    let error_1_remain = &b"xxxabcabcdef"[..];
-    let error_2 = &b"abcxxxabcdef"[..];
-    let parsed_err_2 = Vec::new();
-    let error_2_remain = &b"abcxxxabcdef"[..];
-
-    assert_eq!(counter_2(done), Ok((rest, parsed_done)));
-    assert_eq!(
-      counter_2(incomplete_1),
-      Ok((incomplete_1, parsed_incompl_1))
-    );
-    assert_eq!(
-      counter_2(incomplete_2),
-      Ok((incomplete_2, parsed_incompl_2))
-    );
-    assert_eq!(counter_2(error), Ok((error_remain, parsed_err)));
-    assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1)));
-    assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2)));
-  }
-
-  #[derive(Debug, Clone, PartialEq)]
-  pub struct NilError;
-
-  impl<I> From<(I, ErrorKind)> for NilError {
-    fn from(_: (I, ErrorKind)) -> Self {
-      NilError
-    }
-  }
-
-  impl<I> ParseError<I> for NilError {
-    fn from_error_kind(_: I, _: ErrorKind) -> NilError {
-      NilError
-    }
-    fn append(_: I, _: ErrorKind, _: NilError) -> NilError {
-      NilError
-    }
-  }
-
-  named!(pub number<u32>, map_res!(
-    map_res!(
-      digit,
-      str::from_utf8
-    ),
-    FromStr::from_str
-  ));
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn length_count() {
-    named!(tag_abc, tag!(&b"abc"[..]));
-    named!( cnt<&[u8], Vec<&[u8]> >, length_count!(number, tag_abc) );
-
-    assert_eq!(
-      cnt(&b"2abcabcabcdef"[..]),
-      Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
-    );
-    assert_eq!(cnt(&b"2ab"[..]), Err(Err::Incomplete(Needed::new(3))));
-    assert_eq!(cnt(&b"3abcab"[..]), Err(Err::Incomplete(Needed::new(3))));
-    assert_eq!(
-      cnt(&b"xxx"[..]),
-      Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
-    );
-    assert_eq!(
-      cnt(&b"2abcxxx"[..]),
-      Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
-    );
-  }
-
-  #[test]
-  fn length_data() {
-    named!( take<&[u8], &[u8]>, length_data!(number) );
-
-    assert_eq!(
-      take(&b"6abcabcabcdef"[..]),
-      Ok((&b"abcdef"[..], &b"abcabc"[..]))
-    );
-    assert_eq!(take(&b"3ab"[..]), Err(Err::Incomplete(Needed::new(1))));
-    assert_eq!(
-      take(&b"xxx"[..]),
-      Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
-    );
-    assert_eq!(take(&b"2abcxxx"[..]), Ok((&b"cxxx"[..], &b"ab"[..])));
-  }
-
-  #[test]
-  fn length_value_test() {
-    named!(length_value_1<&[u8], u16 >, length_value!(be_u8, be_u16));
-    named!(length_value_2<&[u8], (u8, u8) >, length_value!(be_u8, tuple!(be_u8, be_u8)));
-
-    let i1 = [0, 5, 6];
-    assert_eq!(
-      length_value_1(&i1),
-      Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
-    );
-    assert_eq!(
-      length_value_2(&i1),
-      Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
-    );
-
-    let i2 = [1, 5, 6, 3];
-    assert_eq!(
-      length_value_1(&i2),
-      Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
-    );
-    assert_eq!(
-      length_value_2(&i2),
-      Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
-    );
-
-    let i3 = [2, 5, 6, 3, 4, 5, 7];
-    assert_eq!(length_value_1(&i3), Ok((&i3[3..], 1286)));
-    assert_eq!(length_value_2(&i3), Ok((&i3[3..], (5, 6))));
-
-    let i4 = [3, 5, 6, 3, 4, 5];
-    assert_eq!(length_value_1(&i4), Ok((&i4[4..], 1286)));
-    assert_eq!(length_value_2(&i4), Ok((&i4[4..], (5, 6))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn fold_many0() {
-    fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
-      acc.push(item);
-      acc
-    }
-    named!(tag_abcd, tag!("abcd"));
-    named!(tag_empty, tag!(""));
-    named!( multi<&[u8],Vec<&[u8]> >, fold_many0!(tag_abcd, Vec::new(), fold_into_vec) );
-    named!( multi_empty<&[u8],Vec<&[u8]> >, fold_many0!(tag_empty, Vec::new(), fold_into_vec) );
-
-    assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
-    assert_eq!(
-      multi(&b"abcdabcdefgh"[..]),
-      Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
-    );
-    assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
-    assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
-    assert_eq!(
-      multi_empty(&b"abcdef"[..]),
-      Err(Err::Error(error_position!(
-        &b"abcdef"[..],
-        ErrorKind::Many0
-      )))
-    );
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn fold_many1() {
-    fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
-      acc.push(item);
-      acc
-    }
-    named!(multi<&[u8],Vec<&[u8]> >, fold_many1!(tag!("abcd"), Vec::new(), fold_into_vec));
-
-    let a = &b"abcdef"[..];
-    let b = &b"abcdabcdefgh"[..];
-    let c = &b"azerty"[..];
-    let d = &b"abcdab"[..];
-
-    let res1 = vec![&b"abcd"[..]];
-    assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
-    let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
-    assert_eq!(
-      multi(c),
-      Err(Err::Error(error_position!(c, ErrorKind::Many1)))
-    );
-    assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  #[cfg(feature = "alloc")]
-  fn fold_many_m_n() {
-    fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
-      acc.push(item);
-      acc
-    }
-    named!(multi<&[u8],Vec<&[u8]> >, fold_many_m_n!(2, 4, tag!("Abcd"), Vec::new(), fold_into_vec));
-
-    let a = &b"Abcdef"[..];
-    let b = &b"AbcdAbcdefgh"[..];
-    let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
-    let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
-    let e = &b"AbcdAb"[..];
-
-    assert_eq!(
-      multi(a),
-      Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
-    );
-    let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
-    let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
-    let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
-    assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
-    assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(4))));
-  }
-
-  #[test]
-  fn many0_count() {
-    named!(
-      count0_nums(&[u8]) -> usize,
-      many0_count!(pair!(digit, tag!(",")))
-    );
-
-    assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1)));
-
-    assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
-
-    assert_eq!(
-      count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
-      Ok((&b"junk"[..], 10))
-    );
-
-    assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0)));
-  }
-
-  #[test]
-  fn many1_count() {
-    named!(
-      count1_nums(&[u8]) -> usize,
-      many1_count!(pair!(digit, tag!(",")))
-    );
-
-    assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
-
-    assert_eq!(
-      count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
-      Ok((&b"junk"[..], 10))
-    );
-
-    assert_eq!(
-      count1_nums(&b"hello"[..]),
-      Err(Err::Error(error_position!(
-        &b"hello"[..],
-        ErrorKind::Many1Count
-      )))
-    );
-  }
-}
diff --git a/src/multi/mod.rs b/src/multi/mod.rs
index 46a59ed..4d1e283 100644
--- a/src/multi/mod.rs
+++ b/src/multi/mod.rs
@@ -1,7 +1,7 @@
 //! Combinators applying their child parser multiple times
 
-#[macro_use]
-mod macros;
+#[cfg(test)]
+mod tests;
 
 use crate::error::ErrorKind;
 use crate::error::ParseError;
@@ -1066,7 +1066,7 @@ where
 
 /// Gets a number from the first parser,
 /// then applies the second parser that many times.
-/// Arguments
+/// # Arguments
 /// * `f` The parser to apply to obtain the count.
 /// * `g` The parser to apply repeatedly.
 /// ```rust
diff --git a/src/number/complete.rs b/src/number/complete.rs
index ffebf23..3e076db 100644
--- a/src/number/complete.rs
+++ b/src/number/complete.rs
@@ -1900,4 +1900,87 @@ mod tests {
       Err(Err::Failure(("", ErrorKind::Digit)))
     );
   }
+
+  #[test]
+  fn configurable_endianness() {
+    use crate::number::Endianness;
+
+    fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+      u16(Endianness::Big)(i)
+    }
+    fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+      u16(Endianness::Little)(i)
+    }
+    assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
+    assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
+
+    fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+      u32(Endianness::Big)(i)
+    }
+    fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+      u32(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tst32(&[0x12, 0x00, 0x60, 0x00]),
+      Ok((&b""[..], 302_014_464_u32))
+    );
+    assert_eq!(
+      le_tst32(&[0x12, 0x00, 0x60, 0x00]),
+      Ok((&b""[..], 6_291_474_u32))
+    );
+
+    fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+      u64(Endianness::Big)(i)
+    }
+    fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+      u64(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 1_297_142_246_100_992_000_u64))
+    );
+    assert_eq!(
+      le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 36_028_874_334_666_770_u64))
+    );
+
+    fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+      i16(Endianness::Big)(i)
+    }
+    fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+      i16(Endianness::Little)(i)
+    }
+    assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
+    assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
+
+    fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+      i32(Endianness::Big)(i)
+    }
+    fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+      i32(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+      Ok((&b""[..], 1_204_224_i32))
+    );
+    assert_eq!(
+      le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+      Ok((&b""[..], 6_296_064_i32))
+    );
+
+    fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+      i64(Endianness::Big)(i)
+    }
+    fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+      i64(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 71_881_672_479_506_432_i64))
+    );
+    assert_eq!(
+      le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 36_028_874_334_732_032_i64))
+    );
+  }
 }
diff --git a/src/number/macros.rs b/src/number/macros.rs
deleted file mode 100644
index 27fdcce..0000000
--- a/src/number/macros.rs
+++ /dev/null
@@ -1,265 +0,0 @@
-//! Parsers recognizing numbers
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u16 integer,
-/// otherwise a little endian u16 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<u16>, u16!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0001)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(1))));
-///
-/// named!(le<u16>, u16!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(1))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u16($i) } else { $crate::number::streaming::le_u16($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u32 integer,
-/// otherwise a little endian u32 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<u32>, u32!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x00010203)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(3))));
-///
-/// named!(le<u32>, u32!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x03020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(3))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u32($i) } else { $crate::number::streaming::le_u32($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u64 integer,
-/// otherwise a little endian u64 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<u64>, u64!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0001020304050607)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(7))));
-///
-/// named!(le<u64>, u64!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0706050403020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(7))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u64($i) } else { $crate::number::streaming::le_u64($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian u128 integer,
-/// otherwise a little endian u128 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<u128>, u128!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x00010203040506070809101112131415)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(15))));
-///
-/// named!(le<u128>, u128!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x15141312111009080706050403020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(15))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-#[cfg(stable_i128)]
-macro_rules! u128 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_u128($i) } else { $crate::number::streaming::le_u128($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i16 integer,
-/// otherwise a little endian i16 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<i16>, i16!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0001)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(1))));
-///
-/// named!(le<i16>, i16!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01abcd"), Ok((&b"abcd"[..], 0x0100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(1))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i16($i) } else { $crate::number::streaming::le_i16($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i32 integer,
-/// otherwise a little endian i32 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<i32>, i32!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x00010203)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(3))));
-///
-/// named!(le<i32>, i32!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03abcd"), Ok((&b"abcd"[..], 0x03020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(3))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i32($i) } else { $crate::number::streaming::le_i32($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i64 integer,
-/// otherwise a little endian i64 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<i64>, i64!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0001020304050607)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(7))));
-///
-/// named!(le<i64>, i64!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"), Ok((&b"abcd"[..], 0x0706050403020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(7))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i64($i) } else { $crate::number::streaming::le_i64($i) } } ););
-
-/// If the parameter is `nom::number::Endianness::Big`, parse a big endian i64 integer,
-/// otherwise a little endian i64 integer.
-///
-/// ```rust
-/// # #[macro_use] extern crate nom;
-/// # use nom::{Err, Needed};
-/// use nom::number::Endianness;
-///
-/// # fn main() {
-/// named!(be<i128>, i128!(Endianness::Big));
-///
-/// assert_eq!(be(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x00010203040506070809101112131415)));
-/// assert_eq!(be(b"\x01"), Err(Err::Incomplete(Needed::new(15))));
-///
-/// named!(le<i128>, i128!(Endianness::Little));
-///
-/// assert_eq!(le(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"), Ok((&b"abcd"[..], 0x15141312111009080706050403020100)));
-/// assert_eq!(le(b"\x01"), Err(Err::Incomplete(Needed::new(15))));
-/// # }
-/// ```
-#[macro_export(local_inner_macros)]
-#[cfg(stable_i128)]
-macro_rules! i128 ( ($i:expr, $e:expr) => ( {if $crate::number::Endianness::Big == $e { $crate::number::streaming::be_i128($i) } else { $crate::number::streaming::le_i128($i) } } ););
-
-#[cfg(test)]
-mod tests {
-  use crate::number::Endianness;
-
-  #[test]
-  fn configurable_endianness() {
-    named!(be_tst16<u16>, u16!(Endianness::Big));
-    named!(le_tst16<u16>, u16!(Endianness::Little));
-    assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
-    assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
-
-    named!(be_tst32<u32>, u32!(Endianness::Big));
-    named!(le_tst32<u32>, u32!(Endianness::Little));
-    assert_eq!(
-      be_tst32(&[0x12, 0x00, 0x60, 0x00]),
-      Ok((&b""[..], 302_014_464_u32))
-    );
-    assert_eq!(
-      le_tst32(&[0x12, 0x00, 0x60, 0x00]),
-      Ok((&b""[..], 6_291_474_u32))
-    );
-
-    named!(be_tst64<u64>, u64!(Endianness::Big));
-    named!(le_tst64<u64>, u64!(Endianness::Little));
-    assert_eq!(
-      be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
-      Ok((&b""[..], 1_297_142_246_100_992_000_u64))
-    );
-    assert_eq!(
-      le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
-      Ok((&b""[..], 36_028_874_334_666_770_u64))
-    );
-
-    named!(be_tsti16<i16>, i16!(Endianness::Big));
-    named!(le_tsti16<i16>, i16!(Endianness::Little));
-    assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
-    assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
-
-    named!(be_tsti32<i32>, i32!(Endianness::Big));
-    named!(le_tsti32<i32>, i32!(Endianness::Little));
-    assert_eq!(
-      be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
-      Ok((&b""[..], 1_204_224_i32))
-    );
-    assert_eq!(
-      le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
-      Ok((&b""[..], 6_296_064_i32))
-    );
-
-    named!(be_tsti64<i64>, i64!(Endianness::Big));
-    named!(le_tsti64<i64>, i64!(Endianness::Little));
-    assert_eq!(
-      be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
-      Ok((&b""[..], 71_881_672_479_506_432_i64))
-    );
-    assert_eq!(
-      le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
-      Ok((&b""[..], 36_028_874_334_732_032_i64))
-    );
-  }
-
-  //FIXME
-  /*
-  #[test]
-  #[cfg(feature = "std")]
-  fn manual_configurable_endianness_test() {
-    let x = 1;
-    let int_parse: Box<Fn(&[u8]) -> IResult<&[u8], u16, (&[u8], ErrorKind)>> = if x == 2 {
-      Box::new(be_u16)
-    } else {
-      Box::new(le_u16)
-    };
-    println!("{:?}", int_parse(&b"3"[..]));
-    assert_eq!(int_parse(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
-  }
-  */
-}
diff --git a/src/number/mod.rs b/src/number/mod.rs
index 6ab2cd5..58c3d51 100644
--- a/src/number/mod.rs
+++ b/src/number/mod.rs
@@ -1,8 +1,5 @@
 //! Parsers recognizing numbers
 
-#[macro_use]
-mod macros;
-
 pub mod complete;
 pub mod streaming;
 
diff --git a/src/number/streaming.rs b/src/number/streaming.rs
index f502519..5d62685 100644
--- a/src/number/streaming.rs
+++ b/src/number/streaming.rs
@@ -1983,4 +1983,87 @@ mod tests {
       Err(Err::Incomplete(Needed::new(1)))
     );
   }
+
+  #[test]
+  fn configurable_endianness() {
+    use crate::number::Endianness;
+
+    fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+      u16(Endianness::Big)(i)
+    }
+    fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+      u16(Endianness::Little)(i)
+    }
+    assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
+    assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
+
+    fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+      u32(Endianness::Big)(i)
+    }
+    fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+      u32(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tst32(&[0x12, 0x00, 0x60, 0x00]),
+      Ok((&b""[..], 302_014_464_u32))
+    );
+    assert_eq!(
+      le_tst32(&[0x12, 0x00, 0x60, 0x00]),
+      Ok((&b""[..], 6_291_474_u32))
+    );
+
+    fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+      u64(Endianness::Big)(i)
+    }
+    fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+      u64(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 1_297_142_246_100_992_000_u64))
+    );
+    assert_eq!(
+      le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 36_028_874_334_666_770_u64))
+    );
+
+    fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+      i16(Endianness::Big)(i)
+    }
+    fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+      i16(Endianness::Little)(i)
+    }
+    assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
+    assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
+
+    fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+      i32(Endianness::Big)(i)
+    }
+    fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+      i32(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+      Ok((&b""[..], 1_204_224_i32))
+    );
+    assert_eq!(
+      le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+      Ok((&b""[..], 6_296_064_i32))
+    );
+
+    fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+      i64(Endianness::Big)(i)
+    }
+    fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+      i64(Endianness::Little)(i)
+    }
+    assert_eq!(
+      be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 71_881_672_479_506_432_i64))
+    );
+    assert_eq!(
+      le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+      Ok((&b""[..], 36_028_874_334_732_032_i64))
+    );
+  }
 }
diff --git a/src/str.rs b/src/str.rs
index a554521..a5e8186 100644
--- a/src/str.rs
+++ b/src/str.rs
@@ -1,13 +1,19 @@
 #[cfg(test)]
 mod test {
-  use crate::{error, error::ErrorKind, Err, IResult};
+  #[cfg(feature = "alloc")]
+  use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1};
+  use crate::{
+    Err, IResult,
+    error::{self, ErrorKind},
+    bytes::complete::{is_a, is_not, tag, take, take_till, take_until},
+  };
 
   #[test]
   fn tagtr_succeed() {
     const INPUT: &str = "Hello World!";
     const TAG: &str = "Hello";
     fn test(input: &str) -> IResult<&str, &str> {
-      tag!(input, TAG)
+      tag(TAG)(input)
     }
 
     match test(INPUT) {
@@ -31,10 +37,12 @@ mod test {
 
   #[test]
   fn tagtr_incomplete() {
+    use crate::bytes::streaming::tag;
+
     const INPUT: &str = "Hello";
     const TAG: &str = "Hello World!";
 
-    let res: IResult<_, _, error::Error<_>> = tag!(INPUT, TAG);
+    let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
     match res {
       Err(Err::Incomplete(_)) => (),
       other => {
@@ -52,7 +60,7 @@ mod test {
     const INPUT: &str = "Hello World!";
     const TAG: &str = "Random"; // TAG must be closer than INPUT.
 
-    let res: IResult<_, _, error::Error<_>> = tag!(INPUT, TAG);
+    let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
     match res {
       Err(Err::Error(_)) => (),
       other => {
@@ -70,7 +78,7 @@ mod test {
     const CONSUMED: &str = "βèƒôřèÂßÇ";
     const LEFTOVER: &str = "áƒƭèř";
 
-    let res: IResult<_, _, error::Error<_>> = take!(INPUT, 9);
+    let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT);
     match res {
       Ok((extra, output)) => {
         assert!(
@@ -100,7 +108,7 @@ mod test {
     const CONSUMED: &str = "βèƒôřè";
     const LEFTOVER: &str = "ÂßÇ∂áƒƭèř";
 
-    let res: IResult<_, _, (_, ErrorKind)> = take_until!(INPUT, FIND);
+    let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
     match res {
       Ok((extra, output)) => {
         assert!(
@@ -127,9 +135,11 @@ mod test {
 
   #[test]
   fn take_s_incomplete() {
+    use crate::bytes::streaming::take;
+
     const INPUT: &str = "βèƒôřèÂßÇá";
 
-    let res: IResult<_, _, (_, ErrorKind)> = take!(INPUT, 13);
+    let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT);
     match res {
       Err(Err::Incomplete(_)) => (),
       other => panic!(
@@ -148,7 +158,11 @@ mod test {
 
   #[test]
   fn take_while() {
-    named!(f<&str,&str>, take_while!(is_alphabetic));
+    use crate::bytes::streaming::take_while;
+
+    fn f(i: &str) -> IResult<&str, &str> {
+      take_while(is_alphabetic)(i)
+    }
     let a = "";
     let b = "abcd";
     let c = "abcd123";
@@ -162,7 +176,11 @@ mod test {
 
   #[test]
   fn take_while1() {
-    named!(f<&str,&str>, take_while1!(is_alphabetic));
+    use crate::bytes::streaming::take_while1;
+
+    fn f(i: &str) -> IResult<&str, &str> {
+      take_while1(is_alphabetic)(i)
+    }
     let a = "";
     let b = "abcd";
     let c = "abcd123";
@@ -186,7 +204,7 @@ mod test {
       c == 'á'
     }
     fn test(input: &str) -> IResult<&str, &str> {
-      take_till!(input, till_s)
+      take_till(till_s)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -212,6 +230,8 @@ mod test {
 
   #[test]
   fn take_while_succeed_none() {
+    use crate::bytes::complete::take_while;
+
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const CONSUMED: &str = "";
     const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř";
@@ -219,7 +239,7 @@ mod test {
       c == '9'
     }
     fn test(input: &str) -> IResult<&str, &str> {
-      take_while!(input, while_s)
+      take_while(while_s)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -250,7 +270,7 @@ mod test {
     const CONSUMED: &str = "βèƒôřèÂßÇ";
     const LEFTOVER: &str = "áƒƭèř";
     fn test(input: &str) -> IResult<&str, &str> {
-      is_not!(input, AVOID)
+      is_not(AVOID)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -276,6 +296,8 @@ mod test {
 
   #[test]
   fn take_while_succeed_some() {
+    use crate::bytes::complete::take_while;
+
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const CONSUMED: &str = "βèƒôřèÂßÇ";
     const LEFTOVER: &str = "áƒƭèř";
@@ -291,7 +313,7 @@ mod test {
         || c == 'Ç'
     }
     fn test(input: &str) -> IResult<&str, &str> {
-      take_while!(input, while_s)
+      take_while(while_s)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -320,7 +342,7 @@ mod test {
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const AVOID: &str = "βúçƙ¥";
     fn test(input: &str) -> IResult<&str, &str> {
-      is_not!(input, AVOID)
+      is_not(AVOID)(input)
     }
     match test(INPUT) {
       Err(Err::Error(_)) => (),
@@ -333,6 +355,8 @@ mod test {
 
   #[test]
   fn take_while1_succeed() {
+    use crate::bytes::complete::take_while1;
+
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const CONSUMED: &str = "βèƒôřèÂßÇ";
     const LEFTOVER: &str = "áƒƭèř";
@@ -348,7 +372,7 @@ mod test {
         || c == 'Ç'
     }
     fn test(input: &str) -> IResult<&str, &str> {
-      take_while1!(input, while1_s)
+      take_while1(while1_s)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -374,10 +398,12 @@ mod test {
 
   #[test]
   fn take_until_incomplete() {
+    use crate::bytes::streaming::take_until;
+
     const INPUT: &str = "βèƒôřè";
     const FIND: &str = "βèƒôřèÂßÇ";
 
-    let res: IResult<_, _, (_, ErrorKind)> = take_until!(INPUT, FIND);
+    let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
     match res {
       Err(Err::Incomplete(_)) => (),
       other => panic!(
@@ -395,7 +421,7 @@ mod test {
     const CONSUMED: &str = "βèƒôřèÂßÇ";
     const LEFTOVER: &str = "áƒƭèř";
     fn test(input: &str) -> IResult<&str, &str> {
-      is_a!(input, MATCH)
+      is_a(MATCH)(input)
     }
     match test(INPUT) {
       Ok((extra, output)) => {
@@ -421,12 +447,14 @@ mod test {
 
   #[test]
   fn take_while1_fail() {
+    use crate::bytes::complete::take_while1;
+
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     fn while1_s(c: char) -> bool {
       c == '9'
     }
     fn test(input: &str) -> IResult<&str, &str> {
-      take_while1!(input, while1_s)
+      take_while1(while1_s)(input)
     }
     match test(INPUT) {
       Err(Err::Error(_)) => (),
@@ -443,7 +471,7 @@ mod test {
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const MATCH: &str = "Ûñℓúçƙ¥";
     fn test(input: &str) -> IResult<&str, &str> {
-      is_a!(input, MATCH)
+      is_a(MATCH)(input)
     }
     match test(INPUT) {
       Err(Err::Error(_)) => (),
@@ -456,10 +484,12 @@ mod test {
 
   #[test]
   fn take_until_error() {
+    use crate::bytes::streaming::take_until;
+
     const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
     const FIND: &str = "Ráñδô₥";
 
-    let res: IResult<_, _, (_, ErrorKind)> = take_until!(INPUT, FIND);
+    let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
     match res {
       Err(Err::Incomplete(_)) => (),
       other => panic!(
@@ -476,7 +506,9 @@ mod test {
     let a = "aabbab";
     let b = "ababcd";
 
-    named!(f <&str,&str>, recognize!(many1!(complete!(alt!( tag!("a") | tag!("b") )))));
+    fn f(i: &str) -> IResult<&str, &str> {
+        recognize(many1(alt((tag("a"), tag("b")))))(i)
+    }
 
     assert_eq!(f(&a[..]), Ok((&a[6..], &a[..])));
     assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4])));
@@ -484,9 +516,9 @@ mod test {
 
   #[test]
   fn utf8_indexing() {
-    named!(dot(&str) -> &str,
-      tag!(".")
-    );
+    fn dot(i: &str) -> IResult<&str, &str> {
+      tag(".")(i)
+    }
 
     let _ = dot("點");
   }
@@ -494,14 +526,11 @@ mod test {
   #[cfg(feature = "alloc")]
   #[test]
   fn case_insensitive() {
-    named!(test<&str,&str>, tag_no_case!("ABcd"));
+    fn test(i: &str) -> IResult<&str, &str> {
+      tag_no_case("ABcd")(i)
+    }
     assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd")));
     assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd")));
     assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD")));
-
-    named!(test2<&str,&str>, tag_no_case!("ABcd"));
-    assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd")));
-    assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd")));
-    assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD")));
   }
 }


Test patch:
diff --git a/src/branch/tests.rs b/src/branch/tests.rs
new file mode 100644
index 0000000..ecd4440
--- /dev/null
+++ b/src/branch/tests.rs
@@ -0,0 +1,142 @@
+use crate::branch::{alt, permutation};
+use crate::bytes::streaming::tag;
+use crate::error::ErrorKind;
+use crate::internal::{Err, IResult, Needed};
+#[cfg(feature = "alloc")]
+use crate::{
+  error::ParseError,
+  lib::std::{
+    fmt::Debug,
+    string::{String, ToString},
+  },
+};
+
+#[cfg(feature = "alloc")]
+#[derive(Debug, Clone, PartialEq)]
+pub struct ErrorStr(String);
+
+#[cfg(feature = "alloc")]
+impl From<u32> for ErrorStr {
+  fn from(i: u32) -> Self {
+    ErrorStr(format!("custom error code: {}", i))
+  }
+}
+
+#[cfg(feature = "alloc")]
+impl<'a> From<&'a str> for ErrorStr {
+  fn from(i: &'a str) -> Self {
+    ErrorStr(format!("custom error message: {}", i))
+  }
+}
+
+#[cfg(feature = "alloc")]
+impl<I: Debug> ParseError<I> for ErrorStr {
+  fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+    ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
+  }
+
+  fn append(input: I, kind: ErrorKind, other: Self) -> Self {
+    ErrorStr(format!(
+      "custom error message: ({:?}, {:?}) - {:?}",
+      input, kind, other
+    ))
+  }
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn alt_test() {
+  fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    Ok((&b""[..], input))
+  }
+
+  #[allow(unused_variables)]
+  fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    Err(Err::Error(ErrorStr("abcd".to_string())))
+  }
+
+  fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    Ok((input, &b""[..]))
+  }
+
+  fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    alt((dont_work, dont_work))(i)
+  }
+  fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    alt((dont_work, work))(i)
+  }
+  fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+    alt((dont_work, dont_work, work2, dont_work))(i)
+  }
+  //named!(alt1, alt!(dont_work | dont_work));
+  //named!(alt2, alt!(dont_work | work));
+  //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work));
+
+  let a = &b"abcd"[..];
+  assert_eq!(
+    alt1(a),
+    Err(Err::Error(error_node_position!(
+      a,
+      ErrorKind::Alt,
+      ErrorStr("abcd".to_string())
+    )))
+  );
+  assert_eq!(alt2(a), Ok((&b""[..], a)));
+  assert_eq!(alt3(a), Ok((a, &b""[..])));
+
+  fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    alt((tag("abcd"), tag("efgh")))(i)
+  }
+  let b = &b"efgh"[..];
+  assert_eq!(alt4(a), Ok((&b""[..], a)));
+  assert_eq!(alt4(b), Ok((&b""[..], b)));
+}
+
+#[test]
+fn alt_incomplete() {
+  fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    alt((tag("a"), tag("bc"), tag("def")))(i)
+  }
+
+  let a = &b""[..];
+  assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+  let a = &b"b"[..];
+  assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+  let a = &b"bcd"[..];
+  assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..])));
+  let a = &b"cde"[..];
+  assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Tag))));
+  let a = &b"de"[..];
+  assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
+  let a = &b"defg"[..];
+  assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
+}
+
+#[test]
+fn permutation_test() {
+  fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
+    permutation((tag("abcd"), tag("efg"), tag("hi")))(i)
+  }
+
+  let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
+
+  let a = &b"abcdefghijk"[..];
+  assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
+  let b = &b"efgabcdhijk"[..];
+  assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
+  let c = &b"hiefgabcdjk"[..];
+  assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
+
+  let d = &b"efgxyzabcdefghi"[..];
+  assert_eq!(
+    perm(d),
+    Err(Err::Error(error_node_position!(
+      &b"efgxyzabcdefghi"[..],
+      ErrorKind::Permutation,
+      error_position!(&b"xyzabcdefghi"[..], ErrorKind::Tag)
+    )))
+  );
+
+  let e = &b"efgabc"[..];
+  assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
+}
diff --git a/src/multi/tests.rs b/src/multi/tests.rs
new file mode 100644
index 0000000..8c3a2d0
--- /dev/null
+++ b/src/multi/tests.rs
@@ -0,0 +1,546 @@
+use super::{length_data, length_value, many0_count, many1_count};
+use crate::{
+  bytes::streaming::tag,
+  character::streaming::digit1 as digit,
+  error::{ErrorKind, ParseError},
+  internal::{Err, IResult, Needed},
+  lib::std::str::{self, FromStr},
+  number::streaming::{be_u16, be_u8},
+  sequence::{pair, tuple},
+};
+#[cfg(feature = "alloc")]
+use crate::{
+  lib::std::vec::Vec,
+  multi::{
+    count, length_count, fold_many0, fold_many1, fold_many_m_n, many0, many1, many_m_n, many_till,
+    separated_list0, separated_list1,
+  },
+};
+
+#[test]
+#[cfg(feature = "alloc")]
+fn separated_list0_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list0(tag(","), tag("abcd"))(i)
+  }
+  fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list0(tag(","), tag(""))(i)
+  }
+  fn empty_sep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list0(tag(""), tag("abc"))(i)
+  }
+  fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list0(tag(".."), tag("abcd"))(i)
+  }
+
+  let a = &b"abcdef"[..];
+  let b = &b"abcd,abcdef"[..];
+  let c = &b"azerty"[..];
+  let d = &b",,abc"[..];
+  let e = &b"abcd,abcd,ef"[..];
+  let f = &b"abc"[..];
+  let g = &b"abcd."[..];
+  let h = &b"abcd,abc"[..];
+  let i = &b"abcabc"[..];
+
+  let res1 = vec![&b"abcd"[..]];
+  assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
+  let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
+  assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new())));
+  let res3 = vec![&b""[..], &b""[..], &b""[..]];
+  assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3)));
+  let i_err_pos = &i[3..];
+  assert_eq!(
+    empty_sep(i),
+    Err(Err::Error(error_position!(
+      i_err_pos,
+      ErrorKind::SeparatedList
+    )))
+  );
+  let res4 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(e), Ok((&b",ef"[..], res4)));
+
+  assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn separated_list1_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list1(tag(","), tag("abcd"))(i)
+  }
+  fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    separated_list1(tag(".."), tag("abcd"))(i)
+  }
+
+  let a = &b"abcdef"[..];
+  let b = &b"abcd,abcdef"[..];
+  let c = &b"azerty"[..];
+  let d = &b"abcd,abcd,ef"[..];
+
+  let f = &b"abc"[..];
+  let g = &b"abcd."[..];
+  let h = &b"abcd,abc"[..];
+
+  let res1 = vec![&b"abcd"[..]];
+  assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
+  let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
+  assert_eq!(
+    multi(c),
+    Err(Err::Error(error_position!(c, ErrorKind::Tag)))
+  );
+  let res3 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(d), Ok((&b",ef"[..], res3)));
+
+  assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many0_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(tag("abcd"))(i)
+  }
+  fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(tag(""))(i)
+  }
+
+  assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
+  assert_eq!(
+    multi(&b"abcdabcdefgh"[..]),
+    Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
+  );
+  assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
+  assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
+  assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
+  assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
+  assert_eq!(
+    multi_empty(&b"abcdef"[..]),
+    Err(Err::Error(error_position!(
+      &b"abcdef"[..],
+      ErrorKind::Many0
+    )))
+  );
+}
+
+#[cfg(nightly)]
+use test::Bencher;
+
+#[cfg(nightly)]
+#[bench]
+fn many0_bench(b: &mut Bencher) {
+  named!(multi<&[u8],Vec<&[u8]> >, many0!(tag!("abcd")));
+  b.iter(|| multi(&b"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"[..]));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many1_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many1(tag("abcd"))(i)
+  }
+
+  let a = &b"abcdef"[..];
+  let b = &b"abcdabcdefgh"[..];
+  let c = &b"azerty"[..];
+  let d = &b"abcdab"[..];
+
+  let res1 = vec![&b"abcd"[..]];
+  assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
+  let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
+  assert_eq!(
+    multi(c),
+    Err(Err::Error(error_position!(c, ErrorKind::Tag)))
+  );
+  assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many_till_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
+    many_till(tag("abcd"), tag("efgh"))(i)
+  }
+
+  let a = b"abcdabcdefghabcd";
+  let b = b"efghabcd";
+  let c = b"azerty";
+
+  let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]);
+  let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]);
+  assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a)));
+  assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b)));
+  assert_eq!(
+    multi(&c[..]),
+    Err(Err::Error(error_node_position!(
+      &c[..],
+      ErrorKind::ManyTill,
+      error_position!(&c[..], ErrorKind::Tag)
+    )))
+  );
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn infinite_many() {
+  fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
+    println!("input: {:?}", input);
+    Err(Err::Error(error_position!(input, ErrorKind::Tag)))
+  }
+
+  // should not go into an infinite loop
+  fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(tst)(i)
+  }
+  let a = &b"abcdef"[..];
+  assert_eq!(multi0(a), Ok((a, Vec::new())));
+
+  fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many1(tst)(i)
+  }
+  let a = &b"abcdef"[..];
+  assert_eq!(
+    multi1(a),
+    Err(Err::Error(error_position!(a, ErrorKind::Tag)))
+  );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many_m_n_test() {
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many_m_n(2, 4, tag("Abcd"))(i)
+  }
+
+  let a = &b"Abcdef"[..];
+  let b = &b"AbcdAbcdefgh"[..];
+  let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
+  let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
+  let e = &b"AbcdAb"[..];
+
+  assert_eq!(
+    multi(a),
+    Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
+  );
+  let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
+  let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
+  let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
+  assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn count_test() {
+  const TIMES: usize = 2;
+  fn cnt_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    count(tag("abc"), TIMES)(i)
+  }
+
+  assert_eq!(
+    cnt_2(&b"abcabcabcdef"[..]),
+    Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
+  );
+  assert_eq!(cnt_2(&b"ab"[..]), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(cnt_2(&b"abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(
+    cnt_2(&b"xxx"[..]),
+    Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+  );
+  assert_eq!(
+    cnt_2(&b"xxxabcabcdef"[..]),
+    Err(Err::Error(error_position!(
+      &b"xxxabcabcdef"[..],
+      ErrorKind::Tag
+    )))
+  );
+  assert_eq!(
+    cnt_2(&b"abcxxxabcdef"[..]),
+    Err(Err::Error(error_position!(
+      &b"xxxabcdef"[..],
+      ErrorKind::Tag
+    )))
+  );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn count_zero() {
+  const TIMES: usize = 0;
+  fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    count(tag("abc"), TIMES)(i)
+  }
+
+  let done = &b"abcabcabcdef"[..];
+  let parsed_done = Vec::new();
+  let rest = done;
+  let incomplete_1 = &b"ab"[..];
+  let parsed_incompl_1 = Vec::new();
+  let incomplete_2 = &b"abcab"[..];
+  let parsed_incompl_2 = Vec::new();
+  let error = &b"xxx"[..];
+  let error_remain = &b"xxx"[..];
+  let parsed_err = Vec::new();
+  let error_1 = &b"xxxabcabcdef"[..];
+  let parsed_err_1 = Vec::new();
+  let error_1_remain = &b"xxxabcabcdef"[..];
+  let error_2 = &b"abcxxxabcdef"[..];
+  let parsed_err_2 = Vec::new();
+  let error_2_remain = &b"abcxxxabcdef"[..];
+
+  assert_eq!(counter_2(done), Ok((rest, parsed_done)));
+  assert_eq!(
+    counter_2(incomplete_1),
+    Ok((incomplete_1, parsed_incompl_1))
+  );
+  assert_eq!(
+    counter_2(incomplete_2),
+    Ok((incomplete_2, parsed_incompl_2))
+  );
+  assert_eq!(counter_2(error), Ok((error_remain, parsed_err)));
+  assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1)));
+  assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2)));
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct NilError;
+
+impl<I> From<(I, ErrorKind)> for NilError {
+  fn from(_: (I, ErrorKind)) -> Self {
+    NilError
+  }
+}
+
+impl<I> ParseError<I> for NilError {
+  fn from_error_kind(_: I, _: ErrorKind) -> NilError {
+    NilError
+  }
+  fn append(_: I, _: ErrorKind, _: NilError) -> NilError {
+    NilError
+  }
+}
+
+named!(pub number<u32>, map_res!(
+  map_res!(
+    digit,
+    str::from_utf8
+  ),
+  FromStr::from_str
+));
+
+#[test]
+#[cfg(feature = "alloc")]
+fn length_count_test() {
+  fn cnt(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    length_count(number, tag("abc"))(i)
+  }
+
+  assert_eq!(
+    cnt(&b"2abcabcabcdef"[..]),
+    Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
+  );
+  assert_eq!(cnt(&b"2ab"[..]), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(cnt(&b"3abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(
+    cnt(&b"xxx"[..]),
+    Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
+  );
+  assert_eq!(
+    cnt(&b"2abcxxx"[..]),
+    Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
+  );
+}
+
+#[test]
+fn length_data_test() {
+  fn take(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    length_data(number)(i)
+  }
+
+  assert_eq!(
+    take(&b"6abcabcabcdef"[..]),
+    Ok((&b"abcdef"[..], &b"abcabc"[..]))
+  );
+  assert_eq!(take(&b"3ab"[..]), Err(Err::Incomplete(Needed::new(1))));
+  assert_eq!(
+    take(&b"xxx"[..]),
+    Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
+  );
+  assert_eq!(take(&b"2abcxxx"[..]), Ok((&b"cxxx"[..], &b"ab"[..])));
+}
+
+#[test]
+fn length_value_test() {
+  fn length_value_1(i: &[u8]) -> IResult<&[u8], u16> {
+    length_value(be_u8, be_u16)(i)
+  }
+  fn length_value_2(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
+    length_value(be_u8, tuple((be_u8, be_u8)))(i)
+  }
+
+  let i1 = [0, 5, 6];
+  assert_eq!(
+    length_value_1(&i1),
+    Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
+  );
+  assert_eq!(
+    length_value_2(&i1),
+    Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
+  );
+
+  let i2 = [1, 5, 6, 3];
+  assert_eq!(
+    length_value_1(&i2),
+    Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
+  );
+  assert_eq!(
+    length_value_2(&i2),
+    Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
+  );
+
+  let i3 = [2, 5, 6, 3, 4, 5, 7];
+  assert_eq!(length_value_1(&i3), Ok((&i3[3..], 1286)));
+  assert_eq!(length_value_2(&i3), Ok((&i3[3..], (5, 6))));
+
+  let i4 = [3, 5, 6, 3, 4, 5];
+  assert_eq!(length_value_1(&i4), Ok((&i4[4..], 1286)));
+  assert_eq!(length_value_2(&i4), Ok((&i4[4..], (5, 6))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many0_test() {
+  fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+    acc.push(item);
+    acc
+  }
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    fold_many0(tag("abcd"), Vec::new(), fold_into_vec)(i)
+  }
+  fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    fold_many0(tag(""), Vec::new(), fold_into_vec)(i)
+  }
+
+  assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
+  assert_eq!(
+    multi(&b"abcdabcdefgh"[..]),
+    Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
+  );
+  assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
+  assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
+  assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
+  assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
+  assert_eq!(
+    multi_empty(&b"abcdef"[..]),
+    Err(Err::Error(error_position!(
+      &b"abcdef"[..],
+      ErrorKind::Many0
+    )))
+  );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many1_test() {
+  fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+    acc.push(item);
+    acc
+  }
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    fold_many1(tag("abcd"), Vec::new(), fold_into_vec)(i)
+  }
+
+  let a = &b"abcdef"[..];
+  let b = &b"abcdabcdefgh"[..];
+  let c = &b"azerty"[..];
+  let d = &b"abcdab"[..];
+
+  let res1 = vec![&b"abcd"[..]];
+  assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
+  let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
+  assert_eq!(
+    multi(c),
+    Err(Err::Error(error_position!(c, ErrorKind::Many1)))
+  );
+  assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many_m_n_test() {
+  fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+    acc.push(item);
+    acc
+  }
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    fold_many_m_n(2, 4, tag("Abcd"), Vec::new(), fold_into_vec)(i)
+  }
+
+  let a = &b"Abcdef"[..];
+  let b = &b"AbcdAbcdefgh"[..];
+  let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
+  let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
+  let e = &b"AbcdAb"[..];
+
+  assert_eq!(
+    multi(a),
+    Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
+  );
+  let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
+  let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
+  let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+  assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
+  assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+fn many0_count_test() {
+  fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> {
+    many0_count(pair(digit, tag(",")))(i)
+  }
+
+  assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1)));
+
+  assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
+
+  assert_eq!(
+    count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
+    Ok((&b"junk"[..], 10))
+  );
+
+  assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0)));
+}
+
+#[test]
+fn many1_count_test() {
+  fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> {
+    many1_count(pair(digit, tag(",")))(i)
+  }
+
+  assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
+
+  assert_eq!(
+    count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
+    Ok((&b"junk"[..], 10))
+  );
+
+  assert_eq!(
+    count1_nums(&b"hello"[..]),
+    Err(Err::Error(error_position!(
+      &b"hello"[..],
+      ErrorKind::Many1Count
+    )))
+  );
+}
diff --git a/tests/custom_errors.rs b/tests/custom_errors.rs
index ad14ee5..2021713 100644
--- a/tests/custom_errors.rs
+++ b/tests/custom_errors.rs
@@ -1,15 +1,14 @@
 #![allow(dead_code)]
-#![cfg_attr(feature = "cargo-clippy", allow(block_in_if_condition_stmt))]
-
-#[macro_use]
-extern crate nom;
 
+use nom::bytes::streaming::tag;
 use nom::character::streaming::digit1 as digit;
+use nom::combinator::verify;
 use nom::error::{ErrorKind, ParseError};
+#[cfg(feature = "alloc")]
+use nom::multi::count;
+use nom::sequence::terminated;
 use nom::IResult;
 
-use std::convert::From;
-
 #[derive(Debug)]
 pub struct CustomError(String);
 
@@ -31,19 +30,19 @@ impl<'a> ParseError<&'a str> for CustomError {
 
 fn test1(input: &str) -> IResult<&str, &str, CustomError> {
   //fix_error!(input, CustomError, tag!("abcd"))
-  tag!(input, "abcd")
+  tag("abcd")(input)
 }
 
 fn test2(input: &str) -> IResult<&str, &str, CustomError> {
   //terminated!(input, test1, fix_error!(CustomError, digit))
-  terminated!(input, test1, digit)
+  terminated(test1, digit)(input)
 }
 
 fn test3(input: &str) -> IResult<&str, &str, CustomError> {
-  verify!(input, test1, |s: &str| { s.starts_with("abcd") })
+  verify(test1, |s: &str| s.starts_with("abcd"))(input)
 }
 
 #[cfg(feature = "alloc")]
 fn test4(input: &str) -> IResult<&str, Vec<&str>, CustomError> {
-  count!(input, test1, 4)
+  count(test1, 4)(input)
 }
diff --git a/tests/float.rs b/tests/float.rs
index 6593f9e..634b189 100644
--- a/tests/float.rs
+++ b/tests/float.rs
@@ -1,34 +1,33 @@
-#[macro_use]
-extern crate nom;
-
+use nom::branch::alt;
+use nom::bytes::complete::tag;
 use nom::character::streaming::digit1 as digit;
+use nom::combinator::{map, map_res, opt, recognize};
+use nom::sequence::{delimited, pair};
+use nom::IResult;
 
 use std::str;
 use std::str::FromStr;
 
-named!(
-  unsigned_float<f32>,
-  map_res!(
-    map_res!(
-      recognize!(alt!(
-        delimited!(digit, tag!("."), opt!(digit)) | delimited!(opt!(digit), tag!("."), digit)
-      )),
-      str::from_utf8
-    ),
-    FromStr::from_str
-  )
-);
+fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> {
+  let float_bytes = recognize(alt((
+    delimited(digit, tag("."), opt(digit)),
+    delimited(opt(digit), tag("."), digit),
+  )));
+  let float_str = map_res(float_bytes, str::from_utf8);
+  map_res(float_str, FromStr::from_str)(i)
+}
 
-named!(
-  float<f32>,
-  map!(
-    pair!(opt!(alt!(tag!("+") | tag!("-"))), unsigned_float),
-    |(sign, value): (Option<&[u8]>, f32)| sign
-      .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None })
-      .unwrap_or(1f32)
-      * value
-  )
-);
+fn float(i: &[u8]) -> IResult<&[u8], f32> {
+  map(
+    pair(opt(alt((tag("+"), tag("-")))), unsigned_float),
+    |(sign, value)| {
+      sign
+        .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None })
+        .unwrap_or(1f32)
+        * value
+    },
+  )(i)
+}
 
 #[test]
 fn unsigned_float_test() {
diff --git a/tests/inference.rs b/tests/inference.rs
deleted file mode 100644
index 4555d7a..0000000
--- a/tests/inference.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-//! test type inference issues in parsee compilation
-//#![feature(trace_macros)]
-#![allow(dead_code)]
-#![allow(unused_comparisons)]
-#![allow(unused_variables)]
-#![allow(unused_imports)]
-
-#[macro_use]
-extern crate nom;
-
-use nom::character::{is_digit, streaming::alpha1 as alpha};
-use std::str;
-
-// issue #617
-named!(multi<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));
-
-// issue #561
-#[cfg(feature = "alloc")]
-named!(
-  value<Vec<Vec<&str>>>,
-  do_parse!(
-    first_line: map_res!(is_not!("\n"), std::str::from_utf8)
-      >> rest:
-        many_m_n!(
-          0,
-          1,
-          separated_list0!(
-            tag!("\n\t"),
-            map_res!(take_while!(call!(|c| c != b'\n')), std::str::from_utf8)
-          )
-        )
-      >> (rest)
-  )
-);
-
-// issue #534
-#[cfg(feature = "alloc")]
-fn wrap_suffix(input: &Option<Vec<&[u8]>>) -> Option<String> {
-  if input.is_some() {
-    // I've tried both of the lines below individually and get the same error.
-    Some("hello".to_string())
-  //Some(str::from_utf8(u).expect("Found invalid UTF-8").to_string())
-  } else {
-    None
-  }
-}
-
-#[cfg(feature = "alloc")]
-named!(parse_suffix<&[u8],Option<String>>,do_parse!(
-  u: opt!(many1!(alt!(
-    complete!(tag!("%")) | complete!(tag!("#"))  | complete!(tag!("@")) | complete!(alpha)
-  ))) >>
-  (wrap_suffix(&u))
-));
diff --git a/tests/ini.rs b/tests/ini.rs
index 3bcec87..e556f44 100644
--- a/tests/ini.rs
+++ b/tests/ini.rs
@@ -1,13 +1,11 @@
-#[macro_use]
-extern crate nom;
-
 use nom::{
   bytes::complete::take_while,
   character::complete::{
     alphanumeric1 as alphanumeric, char, multispace0 as multispace, space0 as space,
   },
-  combinator::map_res,
-  sequence::delimited,
+  combinator::{map, map_res, opt},
+  multi::many0,
+  sequence::{delimited, pair, separated_pair, terminated, tuple},
   IResult,
 };
 
@@ -21,56 +19,39 @@ fn category(i: &[u8]) -> IResult<&[u8], &str> {
   )(i)
 }
 
-fn complete_byte_slice_to_str<'a>(s: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
-  str::from_utf8(s)
+fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> {
+  let (i, key) = map_res(alphanumeric, str::from_utf8)(i)?;
+  let (i, _) = tuple((opt(space), char('='), opt(space)))(i)?;
+  let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8)(i)?;
+  let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n')))(i)?;
+  Ok((i, (key, val)))
+}
+
+fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> {
+  map(many0(terminated(key_value, opt(multispace))), |vec| {
+    vec.into_iter().collect()
+  })(i)
 }
 
-named!(key_value    <&[u8],(&str,&str)>,
-  do_parse!(
-     key: map_res!(alphanumeric, complete_byte_slice_to_str)
-  >>      opt!(space)
-  >>      char!('=')
-  >>      opt!(space)
-  >> val: map_res!(
-           take_while!(call!(|c| c != b'\n' && c != b';')),
-           complete_byte_slice_to_str
-         )
-  >>      opt!(pair!(char!(';'), take_while!(call!(|c| c != b'\n'))))
-  >>      (key, val)
-  )
-);
-
-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<&[u8],(&str,HashMap<&str,&str>)>,
-  do_parse!(
-    category: category         >>
-              opt!(multispace) >>
-    keys: keys_and_values      >>
-    (category, keys)
-  )
-);
-
-named!(categories<&[u8], HashMap<&str, HashMap<&str,&str> > >,
-  map!(
-    many0!(
-      separated_pair!(
-        category,
-        opt!(multispace),
-        map!(
-          many0!(terminated!(key_value, opt!(multispace))),
-          |vec: Vec<_>| vec.into_iter().collect()
-        )
-      )
-    ),
-    |vec: Vec<_>| vec.into_iter().collect()
-  )
-);
+fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> {
+  let (i, category) = terminated(category, opt(multispace))(i)?;
+  let (i, keys) = keys_and_values(i)?;
+  Ok((i, (category, keys)))
+}
+
+fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> {
+  map(
+    many0(separated_pair(
+      category,
+      opt(multispace),
+      map(
+        many0(terminated(key_value, opt(multispace))),
+        |vec: Vec<_>| vec.into_iter().collect(),
+      ),
+    )),
+    |vec: Vec<_>| vec.into_iter().collect(),
+  )(i)
+}
 
 #[test]
 fn parse_category_test() {
diff --git a/tests/ini_str.rs b/tests/ini_str.rs
index 15b8623..3702303 100644
--- a/tests/ini_str.rs
+++ b/tests/ini_str.rs
@@ -1,11 +1,9 @@
-#[macro_use]
-extern crate nom;
-
 use nom::{
-  bytes::complete::{is_a, take_while},
+  bytes::complete::{is_a, tag, take_till, take_while},
   character::complete::{alphanumeric1 as alphanumeric, char, space0 as space},
   combinator::opt,
-  sequence::{delimited, terminated},
+  multi::many0,
+  sequence::{delimited, pair, terminated, tuple},
   IResult,
 };
 
@@ -30,21 +28,20 @@ fn category(i: &str) -> IResult<&str, &str> {
   )(i)
 }
 
-named!(key_value    <&str,(&str,&str)>,
-  do_parse!(
-    key: alphanumeric                              >>
-         opt!(space)                               >>
-         tag!("=")                               >>
-         opt!(space)                               >>
-    val: take_till!(is_line_ending_or_comment)   >>
-         opt!(space)                               >>
-         opt!(pair!(tag!(";"), not_line_ending)) >>
-         opt!(space_or_line_ending)                >>
-    (key, val)
-  )
-);
+fn key_value(i: &str) -> IResult<&str, (&str, &str)> {
+  let (i, key) = alphanumeric(i)?;
+  let (i, _) = tuple((opt(space), tag("="), opt(space)))(i)?;
+  let (i, val) = take_till(is_line_ending_or_comment)(i)?;
+  let (i, _) = opt(space)(i)?;
+  let (i, _) = opt(pair(tag(";"), not_line_ending))(i)?;
+  let (i, _) = opt(space_or_line_ending)(i)?;
+
+  Ok((i, (key, val)))
+}
 
-named!(keys_and_values_aggregator<&str, Vec<(&str, &str)> >, many0!(key_value));
+fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> {
+  many0(key_value)(i)
+}
 
 fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> {
   match keys_and_values_aggregator(input) {
@@ -53,11 +50,13 @@ fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> {
   }
 }
 
-named!(category_and_keys<&str,(&str,HashMap<&str,&str>)>,
-  pair!(category, keys_and_values)
-);
+fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> {
+  pair(category, keys_and_values)(i)
+}
 
-named!(categories_aggregator<&str, Vec<(&str, HashMap<&str,&str>)> >, many0!(category_and_keys));
+fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> {
+  many0(category_and_keys)(i)
+}
 
 fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> {
   match categories_aggregator(input) {
diff --git a/tests/issues.rs b/tests/issues.rs
index 3ffc271..b9c41e9 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -2,15 +2,7 @@
 #![allow(dead_code)]
 #![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
 
-#[macro_use]
-extern crate nom;
-
-use nom::{
-  character::{is_digit, streaming::space1 as space},
-  error::ErrorKind,
-  number::streaming::le_u64,
-  Err, IResult, Needed,
-};
+use nom::{error::ErrorKind, Err, IResult, Needed};
 
 #[allow(dead_code)]
 struct Range {
@@ -26,78 +18,36 @@ pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
   }
 }
 
-//trace_macros!(true);
-
-#[allow(dead_code)]
-named!(range<&[u8], Range>,
-    alt!(
-        do_parse!(
-            start: take_char >>
-            tag!("-")        >>
-            end: take_char   >>
-            (Range {
-                start: start,
-                end:   end,
-            })
-        ) |
-        map!(
-            take_char,
-            |c| {
-                Range {
-                    start: c,
-                    end:   c,
-                }
-            }
-        )
-    )
-);
-
-#[allow(dead_code)]
-named!(literal<&[u8], Vec<char> >,
-    map!(
-        many1!(take_char),
-        |cs| {
-          cs
-        }
-    )
-);
-
-#[test]
-fn issue_58() {
-  let _ = range(&b"abcd"[..]);
-  let _ = literal(&b"abcd"[..]);
-}
-
-//trace_macros!(false);
-
 #[cfg(feature = "std")]
 mod parse_int {
   use nom::HexDisplay;
   use nom::{
     character::streaming::{digit1 as digit, space1 as space},
+    combinator::{complete, map, opt},
+    multi::many0,
     IResult,
   };
   use std::str;
 
-  named!(parse_ints<Vec<i32>>, many0!(spaces_or_int));
+  fn parse_ints(input: &[u8]) -> IResult<&[u8], Vec<i32>> {
+    many0(spaces_or_int)(input)
+  }
 
   fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
     println!("{}", input.to_hex(8));
-    do_parse!(
-      input,
-      opt!(complete!(space))
-        >> res: map!(complete!(digit), |x| {
-          println!("x: {:?}", x);
-          let result = str::from_utf8(x).unwrap();
-          println!("Result: {}", result);
-          println!("int is empty?: {}", x.is_empty());
-          match result.parse() {
-            Ok(i) => i,
-            Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
-          }
-        })
-        >> (res)
-    )
+    let (i, _) = opt(complete(space))(input)?;
+    let (i, res) = map(complete(digit), |x| {
+      println!("x: {:?}", x);
+      let result = str::from_utf8(x).unwrap();
+      println!("Result: {}", result);
+      println!("int is empty?: {}", x.is_empty());
+      match result.parse() {
+        Ok(i) => i,
+        Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
+      }
+    })(i)?;
+
+    Ok((i, res))
   }
 
   #[test]
@@ -114,67 +64,34 @@ mod parse_int {
 
 #[test]
 fn usize_length_bytes_issue() {
+  use nom::multi::length_data;
   use nom::number::streaming::be_u16;
-  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data!(b"012346", be_u16);
-}
-
-/*
- DOES NOT COMPILE
-#[test]
-fn issue_152() {
-  named!(take4, take!(4));
-  named!(xyz, tag!("XYZ"));
-  named!(abc, tag!("abc"));
-
-
-  named!(sw,
-    switch!(take4,
-      b"abcd" => xyz |
-      b"efgh" => abc
-    )
-  );
+  let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16)(b"012346");
 }
-*/
 
 #[test]
 fn take_till_issue() {
-  named!(nothing, take_till!(call!(|_| true)));
+  use nom::bytes::streaming::take_till;
+
+  fn nothing(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    take_till(|_| true)(i)
+  }
 
   assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::new(1))));
   assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
 }
 
-named!(
-  issue_498<Vec<&[u8]>>,
-  separated_list1!(opt!(space), tag!("abcd"))
-);
-
-named!(issue_308(&str) -> bool,
-    do_parse! (
-        tag! ("foo") >>
-        b: alt! (
-            complete!(map! (tag! ("1"), |_: &str|->bool {true})) |
-            value! (false)
-        ) >>
-        (b) ));
-
-#[cfg(feature = "alloc")]
-fn issue_302(input: &[u8]) -> IResult<&[u8], Option<Vec<u64>>> {
-  do_parse!(input, entries: cond!(true, count!(le_u64, 3)) >> (entries))
-}
-
 #[test]
 fn issue_655() {
   use nom::character::streaming::{line_ending, not_line_ending};
-  named!(twolines(&str) -> (&str, &str),
-    do_parse!(
-      l1 : not_line_ending >>
-           line_ending >>
-      l2 : not_line_ending >>
-           line_ending >>
-      ((l1, l2))
-    )
-  );
+  fn twolines(i: &str) -> IResult<&str, (&str, &str)> {
+    let (i, l1) = not_line_ending(i)?;
+    let (i, _) = line_ending(i)?;
+    let (i, l2) = not_line_ending(i)?;
+    let (i, _) = line_ending(i)?;
+
+    Ok((i, (l1, l2)))
+  }
 
   assert_eq!(twolines("foo\nbar\n"), Ok(("", ("foo", "bar"))));
   assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
@@ -182,79 +99,19 @@ fn issue_655() {
   assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
 }
 
-#[test]
-fn issue_721() {
-  named!(f1<&str, u16>, parse_to!(u16));
-  named!(f2<&str, String>, parse_to!(String));
-  assert_eq!(f1("1234"), Ok(("", 1234)));
-  assert_eq!(f2("foo"), Ok(("", "foo".to_string())));
-  //assert_eq!(parse_to!("1234", u16), Ok(("", 1234)));
-  //assert_eq!(parse_to!("foo", String), Ok(("", "foo".to_string())));
-}
-
 #[cfg(feature = "alloc")]
-named!(issue_717<&[u8], Vec<&[u8]> >,
-  separated_list0!(tag!([0x0]), is_not!([0x0u8]))
-);
-
-struct NoPartialEq {
-  value: i32,
-}
-
-named!(issue_724<&str, i32>,
-  do_parse!(
-    metadata: permutation!(
-      map!(tag!("hello"), |_| NoPartialEq { value: 1 }),
-      map!(tag!("world"), |_| NoPartialEq { value: 2 })
-    ) >>
-    (metadata.0.value + metadata.1.value)
-  )
-);
-
-#[test]
-fn issue_752() {
-  assert_eq!(
-    Err::Error(("ab", nom::error::ErrorKind::ParseTo)),
-    parse_to!("ab", usize).unwrap_err()
-  )
-}
-
-fn atom_specials(c: u8) -> bool {
-  c == b'q'
-}
-
-named!(
-  capability<&str>,
-  do_parse!(tag!(" ") >> _atom: map_res!(take_till1!(atom_specials), std::str::from_utf8) >> ("a"))
-);
+fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+  use nom::bytes::complete::{is_not, tag};
+  use nom::multi::separated_list0;
 
-#[test]
-fn issue_759() {
-  assert_eq!(capability(b" abcqd"), Ok((&b"qd"[..], "a")));
+  separated_list0(tag([0x0]), is_not([0x0u8]))(i)
 }
 
-named_args!(issue_771(count: usize)<Vec<u32>>,
-  length_count!(value!(count), call!(nom::number::streaming::be_u32))
-);
-
-/// This test is in a separate module to check that all required symbols are imported in
-/// `escaped_transform!()`. Without the module, the `use`-es of the current module would
-/// mask the error ('"Use of undeclared type or module `Needed`" in escaped_transform!').
-mod issue_780 {
-  named!(issue_780<&str, String>,
-    escaped_transform!(call!(::nom::character::streaming::alpha1), '\\', tag!("n"))
-  );
-}
-
-// issue 617
-named!(digits, take_while1!(is_digit));
-named!(multi_617<&[u8], () >, fold_many0!( digits, (), |_, _| {}));
-
-// Sad :(
-named!(multi_617_fails<&[u8], () >, fold_many0!( take_while1!( is_digit ), (), |_, _| {}));
-
 mod issue_647 {
-  use nom::{error::Error, number::streaming::be_f64, Err};
+  use nom::bytes::streaming::tag;
+  use nom::combinator::complete;
+  use nom::multi::separated_list0;
+  use nom::{error::Error, number::streaming::be_f64, Err, IResult};
   pub type Input<'a> = &'a [u8];
 
   #[derive(PartialEq, Debug, Clone)]
@@ -267,33 +124,31 @@ mod issue_647 {
     input: Input<'a>,
     _cs: &'b f64,
   ) -> Result<(Input<'a>, Vec<f64>), Err<Error<&'a [u8]>>> {
-    separated_list0!(input, complete!(tag!(",")), complete!(be_f64))
+    separated_list0(complete(tag(",")), complete(be_f64))(input)
   }
 
-  named!(data<Input,Data>, map!(
-      do_parse!(
-          c: be_f64 >>
-          tag!("\n") >>
-          v: call!(list,&c) >>
-          (c,v)
-      ), |(c,v)| {
-          Data {
-              c: c,
-              v: v
-          }
-      }
-  ));
+  fn data(input: Input<'_>) -> IResult<Input<'_>, Data> {
+    let (i, c) = be_f64(input)?;
+    let (i, _) = tag("\n")(i)?;
+    let (i, v) = list(i, &c)?;
+    Ok((i, Data { c, v }))
+  }
 }
 
-named!(issue_775, take_till1!(|_| true));
-
 #[test]
 fn issue_848_overflow_incomplete_bits_to_bytes() {
-  named!(take, take!(0x2000000000000000));
-  named!(parser<&[u8], &[u8]>, bits!(bytes!(take)));
+  fn take(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    use nom::bytes::streaming::take;
+    take(0x2000000000000000_usize)(i)
+  }
+  fn parser(i: &[u8]) -> IResult<&[u8], &[u8]> {
+    use nom::bits::{bits, bytes};
+
+    bits(bytes(take))(i)
+  }
   assert_eq!(
     parser(&b""[..]),
-    Err(Err::Failure(error_position!(&b""[..], ErrorKind::TooLarge)))
+    Err(Err::Failure(nom::error_position!(&b""[..], ErrorKind::TooLarge)))
   );
 }
 
@@ -338,16 +193,6 @@ fn issue_1027_convert_error_panic_nonempty() {
   );
 }
 
-named!(issue_962<&[u8], Vec<&[u8]>>,
-    fold_many0!(
-        alt!(tag!("aaaa") | tag!("bbbb")),
-        Vec::new(), |mut acc: Vec<_>, item| {
-            acc.push(item);
-            acc
-        }
-    )
-);
-
 #[test]
 fn issue_1231_bits_expect_fn_closure() {
   use nom::bits::{bits, complete::take};
diff --git a/tests/mp4.rs b/tests/mp4.rs
index c4cee1c..ff60b3d 100644
--- a/tests/mp4.rs
+++ b/tests/mp4.rs
@@ -1,10 +1,11 @@
 #![allow(dead_code)]
 
-#[macro_use]
-extern crate nom;
-
 use nom::{
+  branch::alt,
+  bytes::streaming::{tag, take},
+  combinator::{map, map_res},
   error::ErrorKind,
+  multi::many0,
   number::streaming::{be_f32, be_u16, be_u32, be_u64},
   Err, IResult, Needed,
 };
@@ -93,109 +94,109 @@ pub struct Mvhd64 {
   track_id:      u32
 }
 
-#[allow(non_snake_case)]
-named!(mvhd32 <&[u8], MvhdBox>,
-  do_parse!(
-  version_flags: be_u32 >>
-  created_date:  be_u32 >>
-  modified_date: be_u32 >>
-  scale:         be_u32 >>
-  duration:      be_u32 >>
-  speed:         be_f32 >>
-  volume:        be_u16 >> // actually a 2 bytes decimal
-              take!(10) >>
-  scale_a:       be_f32 >>
-  rotate_b:      be_f32 >>
-  angle_u:       be_f32 >>
-  rotate_c:      be_f32 >>
-  scale_d:       be_f32 >>
-  angle_v:       be_f32 >>
-  position_x:    be_f32 >>
-  position_y:    be_f32 >>
-  scale_w:       be_f32 >>
-  preview:       be_u64 >>
-  poster:        be_u32 >>
-  selection:     be_u64 >>
-  current_time:  be_u32 >>
-  track_id:      be_u32 >>
-  (
-    MvhdBox::M32(Mvhd32 {
-      version_flags: version_flags,
-      created_date:  created_date,
-      modified_date: modified_date,
-      scale:         scale,
-      duration:      duration,
-      speed:         speed,
-      volume:        volume,
-      scaleA:        scale_a,
-      rotateB:       rotate_b,
-      angleU:        angle_u,
-      rotateC:       rotate_c,
-      scaleD:        scale_d,
-      angleV:        angle_v,
-      positionX:     position_x,
-      positionY:     position_y,
-      scaleW:        scale_w,
-      preview:       preview,
-      poster:        poster,
-      selection:     selection,
-      current_time:  current_time,
-      track_id:      track_id
-    })
-  ))
-);
+#[cfg_attr(rustfmt, rustfmt_skip)]
+fn mvhd32(i: &[u8]) -> IResult<&[u8], MvhdBox> {
+  let (i, version_flags) = be_u32(i)?;
+  let (i, created_date) =  be_u32(i)?;
+  let (i, modified_date) = be_u32(i)?;
+  let (i, scale) =         be_u32(i)?;
+  let (i, duration) =      be_u32(i)?;
+  let (i, speed) =         be_f32(i)?;
+  let (i, volume) =        be_u16(i)?; // actually a 2 bytes decimal
+  let (i, _) =             take(10_usize)(i)?;
+  let (i, scale_a) =       be_f32(i)?;
+  let (i, rotate_b) =      be_f32(i)?;
+  let (i, angle_u) =       be_f32(i)?;
+  let (i, rotate_c) =      be_f32(i)?;
+  let (i, scale_d) =       be_f32(i)?;
+  let (i, angle_v) =       be_f32(i)?;
+  let (i, position_x) =    be_f32(i)?;
+  let (i, position_y) =    be_f32(i)?;
+  let (i, scale_w) =       be_f32(i)?;
+  let (i, preview) =       be_u64(i)?;
+  let (i, poster) =        be_u32(i)?;
+  let (i, selection) =     be_u64(i)?;
+  let (i, current_time) =  be_u32(i)?;
+  let (i, track_id) =      be_u32(i)?;
 
-#[allow(non_snake_case)]
-named!(mvhd64 <&[u8], MvhdBox>,
-  do_parse!(
-  version_flags: be_u32 >>
-  created_date:  be_u64 >>
-  modified_date: be_u64 >>
-  scale:         be_u32 >>
-  duration:      be_u64 >>
-  speed:         be_f32 >>
-  volume:        be_u16 >> // actually a 2 bytes decimal
-              take!(10) >>
-  scale_a:       be_f32 >>
-  rotate_b:      be_f32 >>
-  angle_u:       be_f32 >>
-  rotate_c:      be_f32 >>
-  scale_d:       be_f32 >>
-  angle_v:       be_f32 >>
-  position_x:    be_f32 >>
-  position_y:    be_f32 >>
-  scale_w:       be_f32 >>
-  preview:       be_u64 >>
-  poster:        be_u32 >>
-  selection:     be_u64 >>
-  current_time:  be_u32 >>
-  track_id:      be_u32 >>
-  (
-    MvhdBox::M64(Mvhd64 {
-      version_flags: version_flags,
-      created_date:  created_date,
-      modified_date: modified_date,
-      scale:         scale,
-      duration:      duration,
-      speed:         speed,
-      volume:        volume,
-      scaleA:        scale_a,
-      rotateB:       rotate_b,
-      angleU:        angle_u,
-      rotateC:       rotate_c,
-      scaleD:        scale_d,
-      angleV:        angle_v,
-      positionX:     position_x,
-      positionY:     position_y,
-      scaleW:        scale_w,
-      preview:       preview,
-      poster:        poster,
-      selection:     selection,
-      current_time:  current_time,
-      track_id:      track_id
-    })
-  ))
-);
+  let mvhd_box = MvhdBox::M32(Mvhd32 {
+    version_flags,
+    created_date,
+    modified_date,
+    scale,
+    duration,
+    speed,
+    volume,
+    scaleA:    scale_a,
+    rotateB:   rotate_b,
+    angleU:    angle_u,
+    rotateC:   rotate_c,
+    scaleD:    scale_d,
+    angleV:    angle_v,
+    positionX: position_x,
+    positionY: position_y,
+    scaleW:    scale_w,
+    preview,
+    poster,
+    selection,
+    current_time,
+    track_id,
+  });
+
+  Ok((i, mvhd_box))
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+fn mvhd64(i: &[u8]) -> IResult<&[u8], MvhdBox> {
+  let (i, version_flags) = be_u32(i)?;
+  let (i, created_date) =  be_u64(i)?;
+  let (i, modified_date) = be_u64(i)?;
+  let (i, scale) =         be_u32(i)?;
+  let (i, duration) =      be_u64(i)?;
+  let (i, speed) =         be_f32(i)?;
+  let (i, volume) =        be_u16(i)?; // actually a 2 bytes decimal
+  let (i, _) =             take(10_usize)(i)?;
+  let (i, scale_a) =       be_f32(i)?;
+  let (i, rotate_b) =      be_f32(i)?;
+  let (i, angle_u) =       be_f32(i)?;
+  let (i, rotate_c) =      be_f32(i)?;
+  let (i, scale_d) =       be_f32(i)?;
+  let (i, angle_v) =       be_f32(i)?;
+  let (i, position_x) =    be_f32(i)?;
+  let (i, position_y) =    be_f32(i)?;
+  let (i, scale_w) =       be_f32(i)?;
+  let (i, preview) =       be_u64(i)?;
+  let (i, poster) =        be_u32(i)?;
+  let (i, selection) =     be_u64(i)?;
+  let (i, current_time) =  be_u32(i)?;
+  let (i, track_id) =      be_u32(i)?;
+
+  let mvhd_box = MvhdBox::M64(Mvhd64 {
+    version_flags,
+    created_date,
+    modified_date,
+    scale,
+    duration,
+    speed,
+    volume,
+    scaleA:    scale_a,
+    rotateB:   rotate_b,
+    angleU:    angle_u,
+    rotateC:   rotate_c,
+    scaleD:    scale_d,
+    angleV:    angle_v,
+    positionX: position_x,
+    positionY: position_y,
+    scaleW:    scale_w,
+    preview,
+    poster,
+    selection,
+    current_time,
+    track_id,
+  });
+
+  Ok((i, mvhd_box))
+}
 
 #[derive(Debug, Clone)]
 pub enum MvhdBox {
@@ -242,16 +243,22 @@ struct MP4BoxHeader {
   tag: MP4BoxType,
 }
 
-named!(brand_name<&[u8],&str>, map_res!(take!(4), str::from_utf8));
+fn brand_name(input: &[u8]) -> IResult<&[u8], &str> {
+  map_res(take(4_usize), str::from_utf8)(input)
+}
 
-named!(filetype_parser<&[u8], FileType>,
-  do_parse!(
-    m: brand_name          >>
-    v: take!(4)            >>
-    c: many0!(brand_name)  >>
-    (FileType{ major_brand: m, major_brand_version:v, compatible_brands: c })
-  )
-);
+fn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType> {
+  let (i, name) = brand_name(input)?;
+  let (i, version) = take(4_usize)(i)?;
+  let (i, brands) = many0(brand_name)(i)?;
+
+  let ft = FileType {
+    major_brand: name,
+    major_brand_version: version,
+    compatible_brands: brands,
+  };
+  Ok((i, ft))
+}
 
 fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> {
   let res = if input.len() < 100 {
@@ -261,7 +268,7 @@ fn mvhd_box(input: &[u8]) -> IResult<&[u8], MvhdBox> {
   } else if input.len() == 112 {
     mvhd64(input)
   } else {
-    Err(Err::Error(error_position!(input, ErrorKind::TooLarge)))
+    Err(Err::Error(nom::error_position!(input, ErrorKind::TooLarge)))
   };
   println!("res: {:?}", res);
   res
@@ -271,48 +278,43 @@ fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
   Ok((input, MP4BoxType::Unknown))
 }
 
-//named!(box_type<&[u8], MP4BoxType>,
 fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
-  alt!(input,
-    tag!("ftyp") => { |_| MP4BoxType::Ftyp } |
-    tag!("moov") => { |_| MP4BoxType::Moov } |
-    tag!("mdat") => { |_| MP4BoxType::Mdat } |
-    tag!("free") => { |_| MP4BoxType::Free } |
-    tag!("skip") => { |_| MP4BoxType::Skip } |
-    tag!("wide") => { |_| MP4BoxType::Wide } |
-    unknown_box_type
-  )
+  alt((
+    map(tag("ftyp"), |_| MP4BoxType::Ftyp),
+    map(tag("moov"), |_| MP4BoxType::Moov),
+    map(tag("mdat"), |_| MP4BoxType::Mdat),
+    map(tag("free"), |_| MP4BoxType::Free),
+    map(tag("skip"), |_| MP4BoxType::Skip),
+    map(tag("wide"), |_| MP4BoxType::Wide),
+    unknown_box_type,
+  ))(input)
 }
 
 // warning, an alt combinator with 9 branches containing a tag combinator
 // can make the compilation very slow. Use functions as sub parsers,
-// or split into multiple alt! parsers if it gets slow
-named!(moov_type<&[u8], MP4BoxType>,
-  alt!(
-    tag!("mdra") => { |_| MP4BoxType::Mdra } |
-    tag!("dref") => { |_| MP4BoxType::Dref } |
-    tag!("cmov") => { |_| MP4BoxType::Cmov } |
-    tag!("rmra") => { |_| MP4BoxType::Rmra } |
-    tag!("iods") => { |_| MP4BoxType::Iods } |
-    tag!("mvhd") => { |_| MP4BoxType::Mvhd } |
-    tag!("clip") => { |_| MP4BoxType::Clip } |
-    tag!("trak") => { |_| MP4BoxType::Trak } |
-    tag!("udta") => { |_| MP4BoxType::Udta }
-  )
-);
+// or split into multiple alt parsers if it gets slow
+fn moov_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
+  alt((
+    map(tag("mdra"), |_| MP4BoxType::Mdra),
+    map(tag("dref"), |_| MP4BoxType::Dref),
+    map(tag("cmov"), |_| MP4BoxType::Cmov),
+    map(tag("rmra"), |_| MP4BoxType::Rmra),
+    map(tag("iods"), |_| MP4BoxType::Iods),
+    map(tag("mvhd"), |_| MP4BoxType::Mvhd),
+    map(tag("clip"), |_| MP4BoxType::Clip),
+    map(tag("trak"), |_| MP4BoxType::Trak),
+    map(tag("udta"), |_| MP4BoxType::Udta),
+  ))(input)
+}
 
-named!(box_header<&[u8],MP4BoxHeader>,
-  do_parse!(
-    length: be_u32 >>
-    tag: box_type  >>
-    (MP4BoxHeader{ length: length, tag: tag})
-  )
-);
+fn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> {
+  let (i, length) = be_u32(input)?;
+  let (i, tag) = box_type(i)?;
+  Ok((i, MP4BoxHeader { length, tag }))
+}
 
-named!(moov_header<&[u8],MP4BoxHeader>,
-  do_parse!(
-    length: be_u32 >>
-    tag: moov_type >>
-    (MP4BoxHeader{ length: length, tag: tag})
-  )
-);
+fn moov_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> {
+  let (i, length) = be_u32(input)?;
+  let (i, tag) = moov_type(i)?;
+  Ok((i, MP4BoxHeader { length, tag }))
+}
diff --git a/tests/named_args.rs b/tests/named_args.rs
deleted file mode 100644
index 9ba4b3a..0000000
--- a/tests/named_args.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-#[macro_use]
-extern crate nom;
-
-use nom::{
-  branch::alt,
-  bytes::complete::tag,
-  character::complete::{digit1 as digit, space0 as space},
-  sequence::{delimited, pair, preceded},
-};
-
-// Parser definition
-
-use std::str;
-use std::str::FromStr;
-
-use self::Operator::*;
-
-enum Operator {
-  Slash,
-  Star,
-}
-
-impl Operator {
-  fn to_str(&self) -> &'static str {
-    match *self {
-      Slash => "/",
-      Star => "*",
-    }
-  }
-}
-
-// Parse the specified `Operator`.
-named_args!(operator(op: Operator) <&[u8], &[u8]>,
-    call!(tag(op.to_str()))
-);
-
-// We parse any expr surrounded by the tags `open_tag` and `close_tag`, ignoring all whitespaces around those
-named_args!(brackets<'a>(open_tag: &str, close_tag: &str) <&'a[u8], i64>,
-  call!(delimited(
-    space,
-    delimited(tag(open_tag), preceded(space, expr), preceded(space, tag(close_tag))),
-    space
-  ))
-);
-
-fn byte_slice_to_str<'a>(s: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
-  str::from_utf8(s)
-}
-
-// We transform an integer string into a i64, ignoring surrounding whitespaces
-// We look for a digit suite, and try to convert it.
-// If either str::from_utf8 or FromStr::from_str fail,
-// we fallback to the brackets parser defined above
-named!(factor<&[u8], i64>, alt!(
-    map_res!(
-      map_res!(
-        call!(delimited(space, digit, space)),
-        byte_slice_to_str
-      ),
-      FromStr::from_str
-    )
-  | call!(brackets, "(", ")")
-  )
-);
-
-// We read an initial factor and for each time we find
-// a * or / operator followed by another factor, we do
-// the math by folding everything
-named!(term <&[u8], i64>, do_parse!(
-    init: factor >>
-    res:  fold_many0!(
-        pair!(alt!(call!(operator, Star) | call!(operator, Slash)), factor),
-        init,
-        |acc, (op, val): (&[u8], i64)| {
-            if (op[0] as char) == '*' { acc * val } else { acc / val }
-        }
-    ) >>
-    (res)
-  )
-);
-
-named!(expr <&[u8], i64>, do_parse!(
-    init: term >>
-    res:  fold_many0!(
-        call!(pair(alt((tag("+"), tag("-"))), term)),
-        init,
-        |acc, (op, val): (&[u8], i64)| {
-            if (op[0] as char) == '+' { acc + val } else { acc - val }
-        }
-    ) >>
-    (res)
-  )
-);
-
-#[test]
-fn factor_test() {
-  assert_eq!(factor(&b"3"[..]), Ok((&b""[..], 3)));
-  assert_eq!(factor(&b" 12"[..]), Ok((&b""[..], 12)));
-  assert_eq!(factor(&b"537  "[..]), Ok((&b""[..], 537)));
-  assert_eq!(factor(&b"  24   "[..]), Ok((&b""[..], 24)));
-}
-
-#[test]
-fn term_test() {
-  assert_eq!(term(&b" 12 *2 /  3"[..]), Ok((&b""[..], 8)));
-  assert_eq!(term(&b" 2* 3  *2 *2 /  3"[..]), Ok((&b""[..], 8)));
-  assert_eq!(term(&b" 48 /  3/2"[..]), Ok((&b""[..], 8)));
-}
-
-#[test]
-fn expr_test() {
-  assert_eq!(expr(&b" 1 +  2 "[..]), Ok((&b""[..], 3)));
-  assert_eq!(expr(&b" 12 + 6 - 4+  3"[..]), Ok((&b""[..], 17)));
-  assert_eq!(expr(&b" 1 + 2*3 + 4"[..]), Ok((&b""[..], 11)));
-}
-
-#[test]
-fn parens_test() {
-  assert_eq!(expr(&b" (  2 )"[..]), Ok((&b""[..], 2)));
-  assert_eq!(expr(&b" 2* (  3 + 4 ) "[..]), Ok((&b""[..], 14)));
-  assert_eq!(expr(&b"  2*2 / ( 5 - 1) + 3"[..]), Ok((&b""[..], 4)));
-}
diff --git a/tests/overflow.rs b/tests/overflow.rs
index c66b9f4..ea513bb 100644
--- a/tests/overflow.rs
+++ b/tests/overflow.rs
@@ -1,39 +1,19 @@
 #![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
 #![cfg(target_pointer_width = "64")]
 
-#[macro_use]
-extern crate nom;
-
+use nom::bytes::streaming::take;
+#[cfg(feature = "alloc")]
+use nom::multi::{length_data, many0};
 #[cfg(feature = "alloc")]
 use nom::number::streaming::be_u64;
-use nom::{Err, Needed};
+use nom::sequence::tuple;
+use nom::{Err, IResult, Needed};
 
 // Parser definition
 
 // We request a length that would trigger an overflow if computing consumed + requested
-named!(parser01<&[u8],()>,
-    do_parse!(
-        hdr: take!(1) >>
-        data: take!(18446744073709551615) >>
-        ({
-          let _ = hdr;
-          let _ = data;
-          ()
-        })
-    )
-);
-
-// We request a length that would trigger an overflow if computing consumed + requested
-named!(parser02<&[u8],(&[u8],&[u8])>,
-    tuple!(take!(1),take!(18446744073709551615))
-);
-
-#[test]
-fn overflow_incomplete_do_parse() {
-  assert_eq!(
-    parser01(&b"3"[..]),
-    Err(Err::Incomplete(Needed::new(18446744073709551615)))
-  );
+fn parser02(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+  tuple((take(1_usize), take(18446744073709551615_usize)))(i)
 }
 
 #[test]
@@ -47,7 +27,9 @@ fn overflow_incomplete_tuple() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_length_bytes() {
-  named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(length_data(be_u64))(i)
+  }
 
   // Trigger an overflow in length_data
   assert_eq!(
@@ -59,7 +41,9 @@ fn overflow_incomplete_length_bytes() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_many0() {
-  named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(length_data(be_u64))(i)
+  }
 
   // Trigger an overflow in many0
   assert_eq!(
@@ -71,7 +55,11 @@ fn overflow_incomplete_many0() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_many1() {
-  named!(multi<&[u8], Vec<&[u8]> >, many1!( length_data!(be_u64) ) );
+  use nom::multi::many1;
+
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many1(length_data(be_u64))(i)
+  }
 
   // Trigger an overflow in many1
   assert_eq!(
@@ -83,7 +71,11 @@ fn overflow_incomplete_many1() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_many_till() {
-  named!(multi<&[u8], (Vec<&[u8]>, &[u8]) >, many_till!( length_data!(be_u64), tag!("abc") ) );
+  use nom::{bytes::complete::tag, multi::many_till};
+
+  fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
+    many_till(length_data(be_u64), tag("abc"))(i)
+  }
 
   // Trigger an overflow in many_till
   assert_eq!(
@@ -95,7 +87,11 @@ fn overflow_incomplete_many_till() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_many_m_n() {
-  named!(multi<&[u8], Vec<&[u8]> >, many_m_n!(2, 4, length_data!(be_u64) ) );
+  use nom::multi::many_m_n;
+
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many_m_n(2, 4, length_data(be_u64))(i)
+  }
 
   // Trigger an overflow in many_m_n
   assert_eq!(
@@ -107,7 +103,11 @@ fn overflow_incomplete_many_m_n() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_count() {
-  named!(counter<&[u8], Vec<&[u8]> >, count!( length_data!(be_u64), 2 ) );
+  use nom::multi::count;
+
+  fn counter(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    count(length_data(be_u64), 2)(i)
+  }
 
   assert_eq!(
     counter(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]),
@@ -118,8 +118,12 @@ fn overflow_incomplete_count() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_length_count() {
+  use nom::multi::length_count;
   use nom::number::streaming::be_u8;
-  named!(multi<&[u8], Vec<&[u8]> >, length_count!( be_u8, length_data!(be_u64) ) );
+
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    length_count(be_u8, length_data(be_u64))(i)
+  }
 
   assert_eq!(
     multi(&b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee"[..]),
@@ -130,7 +134,9 @@ fn overflow_incomplete_length_count() {
 #[test]
 #[cfg(feature = "alloc")]
 fn overflow_incomplete_length_data() {
-  named!(multi<&[u8], Vec<&[u8]> >, many0!( length_data!(be_u64) ) );
+  fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+    many0(length_data(be_u64))(i)
+  }
 
   assert_eq!(
     multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]),
diff --git a/tests/reborrow_fold.rs b/tests/reborrow_fold.rs
index b53555b..d356176 100644
--- a/tests/reborrow_fold.rs
+++ b/tests/reborrow_fold.rs
@@ -1,18 +1,31 @@
 #![allow(dead_code)]
-#![allow(unused_variables)]
-
-#[macro_use]
-extern crate nom;
+// #![allow(unused_variables)]
 
 use std::str;
 
-named_args!(atom<'a>(tomb: &'a mut ())<String>,
-            map!(map_res!(is_not!(" \t\r\n()"), str::from_utf8), ToString::to_string));
+use nom::bytes::complete::is_not;
+use nom::character::complete::char;
+use nom::combinator::{map, map_res};
+use nom::multi::fold_many0;
+use nom::sequence::delimited;
+use nom::IResult;
+
+fn atom<'a>(_tomb: &'a mut ()) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], String> {
+  move |input| {
+    map(
+      map_res(is_not(" \t\r\n"), str::from_utf8),
+      ToString::to_string,
+    )(input)
+  }
+}
 
-/*FIXME: should we support the use case of borrowing data mutably in a parser?
-named_args!(list<'a>(tomb: &'a mut ())<String>,
-  delimited!(
-    char!('('),
-    fold_many0!(call!(atom, tomb), "".to_string(), |acc: String, next: String| acc + next.as_str()),
-    char!(')')));
-*/
+// FIXME: should we support the use case of borrowing data mutably in a parser?
+fn list<'a>(i: &'a [u8], tomb: &'a mut ()) -> IResult<&'a [u8], String> {
+  delimited(
+    char('('),
+    fold_many0(atom(tomb), String::new(), |acc: String, next: String| {
+      acc + next.as_str()
+    }),
+    char(')'),
+  )(i)
+}
diff --git a/tests/test1.rs b/tests/test1.rs
deleted file mode 100644
index 85c442f..0000000
--- a/tests/test1.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-#![cfg(feature = "stream")]
-
-#[macro_use]
-extern crate nom;
-
-use nom::{not_line_ending, IResult};
-
-use std::fmt::Debug;
-
-/*
-#[test]
-#[allow(unused_must_use)]
-fn tag() {
-  FileProducer::new("assets/links.txt", 20).map(|producer: FileProducer| {
-    let mut p = producer;
-    p.refill();
-
-    consumer_from_parser!(PrintConsumer<()>, flat_map!(map_res!(tag!("https!"), str::from_utf8), print));
-    let mut cs = PrintConsumer::new();
-    for _ in 1..4 {
-      p.apply(&mut cs);
-    }
-  });
-}
-*/
-
-pub fn print<T: Debug>(input: T) -> IResult<T, ()> {
-  println!("{:?}", input);
-  Ok((input, ()))
-}
-
-#[test]
-fn is_not() {
-  //is_not!(foo b"\r\n");
-  named!(foo<&[u8],&[u8]>, is_not!(&b"\r\n"[..]));
-  let a = &b"ab12cd\nefgh"[..];
-  assert_eq!(foo(a), Ok((&b"\nefgh"[..], &b"ab12cd"[..])));
-}
-
-#[test]
-fn exported_public_method_defined_by_macro() {
-  let a = &b"ab12cd\nefgh"[..];
-  assert_eq!(not_line_ending(a), Ok((&b"\nefgh"[..], &b"ab12cd"[..])));
-}