Repository: Geal/nom
Pull request #812 (2018-07-06 22:17:50)

Remove weird heading lines in migration guides.
Not sure about the meaning of those lines. If you refuse the PR because
of them being useful, please explain to me; I’m curious!

coveralls: 
[![Coverage Status](https://coveralls.io/builds/17873840/badge)](https://coveralls.io/builds/17873840)

Coverage remained the same at 87.542% when pulling **9782be62d0961a9221b358db16ee80ceec3eabdb on phaazon:fix-nom4-migration-guide-typo** into **a88a6f8d3fe3cf41ef682bbfec1fd72f08edcf95 on Geal:master**.


Patch:
diff --git a/.travis.yml b/.travis.yml
index 82f45be..f509570 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -67,6 +67,13 @@ addons:
     sources:
       - kalakris-cmake
 
+cache:
+  directories:
+    - /home/travis/.cargo
+
+before_cache:
+  - rm -rf /home/travis/.cargo/registry
+
 script:
   - eval cargo build --verbose $FEATURES
   - eval cargo test --verbose $FEATURES
diff --git a/Cargo.toml b/Cargo.toml
index 7712935..7f5afe1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,6 +45,10 @@ default-features = false
 #git = "https://github.com/carllerche/bytes"
 #rev = "a7d38e29"
 
+[package.metadata.docs.rs]
+features = [ "alloc", "std", "regexp", "regexp_macros", "verbose-errors" ]
+all-features = true
+
 [[test]]
 name = "arithmetic"
 
diff --git a/README.md b/README.md
index 6dd661a..d38e8da 100644
--- a/README.md
+++ b/README.md
@@ -257,6 +257,7 @@ Here is a list of known projects using nom:
   * [IMAP](https://github.com/djc/imap-proto)
   * [IRC](https://github.com/Detegr/RBot-parser)
   * [Pcap-NG](https://github.com/richo/pcapng-rs)
+  * [Pcap](https://github.com/ithinuel/pcap-rs)
   * [NTP](https://github.com/rusticata/ntp-parser)
   * [SNMP](https://github.com/rusticata/snmp-parser)
   * [DER](https://github.com/rusticata/der-parser)
diff --git a/doc/home.md b/doc/home.md
index aba6163..179a96d 100644
--- a/doc/home.md
+++ b/doc/home.md
@@ -8,7 +8,7 @@ To get started using nom, you can include it in your Rust projects from
 * [Reference documentation](http://rust.unhandledexpression.com/nom/)
 * [Gitter chat room](https://gitter.im/Geal/nom). You can also go to the #nom IRC
 channel on irc.mozilla.org, or ping 'geal' on Mozilla, Freenode, Geeknode or oftc IRC
-* [Tutorial about parsing ISO8601 dates](https://fnordig.de/2015/07/16/omnomnom-parsing-iso8601-dates-using-nom/)
+* [Tutorial about parsing ISO8601 dates](https://github.com/badboy/iso8601/blob/338b3d1a9ca220372292f631a3bc2e5176cca331/docs/parsing-iso8601-dates-using-nom.md)
 * [Making a new parser from scratch](making_a_new_parser_from_scratch.html)
 (general tips on writing a parser and code architecture)
 * [How to handle parser errors](error_management.html)
diff --git a/doc/how_nom_macros_work.md b/doc/how_nom_macros_work.md
index 578f63f..5f5c97f 100644
--- a/doc/how_nom_macros_work.md
+++ b/doc/how_nom_macros_work.md
@@ -140,7 +140,7 @@ transformed with the second pattern:
 opt!(call!(digit))
 ```
 
-The `call!` macro transforms `call!(input, f)` into `f(i)`. If you need to pass more parameters to the function, you can Use `call!(input, f, arg, arg2)` to get `f(i, arg, arg2)`.
+The `call!` macro transforms `call!(input, f)` into `f(input)`. If you need to pass more parameters to the function, you can Use `call!(input, f, arg, arg2)` to get `f(input, arg, arg2)`.
 
 ## Using the macro's parameters
 
diff --git a/doc/making_a_new_parser_from_scratch.md b/doc/making_a_new_parser_from_scratch.md
index e1b43fe..c6b2f92 100644
--- a/doc/making_a_new_parser_from_scratch.md
+++ b/doc/making_a_new_parser_from_scratch.md
@@ -251,7 +251,7 @@ This particular one is caused by `named!` generating a function returning a `IRe
 
 There are a few tools you can use to debug how code is generated.
 
-## trace_macros
+## trace\_macros
 
 The `trace_macros` feature show how macros are applied. To use it, add `#![feature(trace_macros)]` at the top of your file (you need Rust nightly for this), then apply it like this:
 
diff --git a/doc/upgrading_to_nom_1.md b/doc/upgrading_to_nom_1.md
index 2c3a201..bce06c2 100644
--- a/doc/upgrading_to_nom_1.md
+++ b/doc/upgrading_to_nom_1.md
@@ -1,4 +1,4 @@
-% Upgrading to nom 1.0
+# Upgrading to nom 1.0
 
 The 1.0 release of nom is one of the biggest since the beginning of the project. Its goal was to rework some core parts to be more flexible, and clean code that was awkward or unclear. This resulted in breaking changes, that I hope will not happen again in the future (but hey, we are Rust developers, breaking changes are FUN for us!).
 
diff --git a/doc/upgrading_to_nom_2.md b/doc/upgrading_to_nom_2.md
index 0eb2abc..257d262 100644
--- a/doc/upgrading_to_nom_2.md
+++ b/doc/upgrading_to_nom_2.md
@@ -1,5 +1,3 @@
-% Upgrading to nom 2.0
-
 # Upgrading to nom 2.0
 
 The 2.0 release of nom adds a lot of new features, but it was also time for a big cleanup of badly named functions and macros, awkwardly written features and redundant functionality. So this release has some breaking changes, but most of them are harmless.
@@ -106,7 +104,7 @@ you can fix it with:
 +    c == 0x0
 ```
 
-## length_value, length_bytes refactoring
+## `length_value!`, `length_bytes!` refactoring
 
 The "length-value" pattern usually indicates that we get a length from the input, then take a slice of that size from the input, and convert that to a value of the type we need. The `length_value!` macro was using the length parameter to apply the value parser a specific number of times.
 
@@ -133,7 +131,7 @@ error[E0308]: mismatched types
          sig_hash_algs_len: be_u16 ~
 ```
 
-## error! does not exist anymore
+## `error!` does not exist anymore
 
 The `error!` macro, that was used to return a parsing error without backtracking through the parser tree, is now called `return_error!`. This change was done because the "log" crate also uses an `error!` macro, and they complained about the name conflict to nom instead of complaining to log, much to my dismay.
 
diff --git a/doc/upgrading_to_nom_4.md b/doc/upgrading_to_nom_4.md
index a28c4bd..a7ebcf0 100644
--- a/doc/upgrading_to_nom_4.md
+++ b/doc/upgrading_to_nom_4.md
@@ -1,5 +1,3 @@
-% Upgrading to nom 4.0
-
 # Upgrading to nom 4.0
 
 The nom 4.0 is a nearly complete rewrite of nom's internal structures, along with a cleanup of a lot of parser and combinators whose semantics were unclear. Upgrading from previous nom versions can require a lot of changes, especially if you have a lot of unit tests. But most of those changes are pretty straightforward.
@@ -231,10 +229,7 @@ If those types feel a bit long to write everywhere in the parsers, it's possible
 to alias them like this:
 
 ```rust,ignore
-type Input<'a> = CompleteByteSlice<'a>;
-pub fn Input<'a>(input:&'a[u8]) -> Input<'a> {
-  CompleteByteSlice(input)
-}
+use nom::types::CompleteByteSlice as Input;
 ```
 
 ## Custom error types
diff --git a/src/bits.rs b/src/bits.rs
index f0c3e77..ffb7531 100644
--- a/src/bits.rs
+++ b/src/bits.rs
@@ -159,7 +159,7 @@ macro_rules! bytes_impl (
   ($macro_i:expr, $submac:ident!( $($args:tt)* )) => (
     {
       use $crate::lib::std::result::Result::*;
-      use $crate::{Err,Needed};
+      use $crate::{Err,Needed,Context};
 
       let inp;
       if $macro_i.1 % 8 != 0 {
@@ -219,7 +219,7 @@ macro_rules! bytes_impl (
   ($macro_i:expr, $submac:ident!( $($args:tt)* )) => (
     {
       use $crate::lib::std::result::Result::*;
-      use $crate::{Err,Needed};
+      use $crate::{Err,Needed,Context};
 
       let inp;
       if $macro_i.1 % 8 != 0 {
diff --git a/src/bytes.rs b/src/bytes.rs
index ea37ffd..d5c0a47 100644
--- a/src/bytes.rs
+++ b/src/bytes.rs
@@ -300,6 +300,7 @@ macro_rules! escaped_transform (
       use $crate::ExtendInto;
       use $crate::InputIter;
       use $crate::InputLength;
+      use $crate::Needed;
       use $crate::Slice;
       use $crate::need_more;
 
@@ -759,7 +760,7 @@ macro_rules! take_until_and_consume1 (
 /// consumes data until it finds the specified tag.
 ///
 /// The remainder still contains the tag.
-/// (As opposed to `take_until!` which removes it from the remainder.)
+/// (As opposed to `take_until_and_consume!` which removes it from the remainder.)
 ///
 /// # Example
 /// ```
diff --git a/src/lib.rs b/src/lib.rs
index 8d391be..908eab6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -166,7 +166,7 @@
 //! It can have the following values:
 //!
 //! - a correct result `Ok((I,O))` with the first element being the remaining of the input (not parsed yet), and the second the output value;
-//! - an error `Err(Err::Error(c))` with `c` an enum that contians an error code with its position in the input, and optionally a chain of accumulated errors;
+//! - an error `Err(Err::Error(c))` with `c` an enum that contains an error code with its position in the input, and optionally a chain of accumulated errors;
 //! - an error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed
 //! - an error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: we cannot backtrack and test another parser
 //!
diff --git a/src/macros.rs b/src/macros.rs
index ee3dae5..66725e6 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -698,7 +698,7 @@ macro_rules! parse_to (
       let res: Option<$t> = ($i).parse_to();
       match res {
         Some(output) => Ok(($i.slice($i.input_len()..), output)),
-        None         => Err(Err::Error(Context::Code($i, ErrorKind::MapOpt::<u32>)))
+        None         => Err(Err::Error(Context::Code($i, ErrorKind::ParseTo::<u32>)))
       }
     }
   );
@@ -977,7 +977,6 @@ macro_rules! cond_with_error(
   ($i:expr, $cond:expr, $submac:ident!( $($args:tt)* )) => (
     {
       use $crate::lib::std::result::Result::*;
-      use $crate::{Convert,Err,Needed,IResult};
 
       if $cond {
         match $submac!($i, $($args)*) {
@@ -1544,4 +1543,19 @@ mod tests {
     );
     assert_eq!(test(&b"abcdefg"[..]), Ok((&b"fg"[..], &b"abcde"[..])));
   }
+
+  #[test]
+  fn parse_to() {
+    use util::Convert;
+
+    assert_eq!(
+      parse_to!("ab", usize),
+      Err(Err::Error(error_position!(
+        "ab",
+        ErrorKind::ParseTo
+      )))
+    );
+    assert_eq!(parse_to!("42", usize), Ok(("", 42)));
+    assert_eq!(ErrorKind::<u64>::convert(ErrorKind::ParseTo::<u32>), ErrorKind::ParseTo::<u64>);
+  }
 }
diff --git a/src/multi.rs b/src/multi.rs
index c6aed73..b7e2591 100644
--- a/src/multi.rs
+++ b/src/multi.rs
@@ -295,6 +295,7 @@ macro_rules! many0(
 /// # #[macro_use] extern crate nom;
 /// # use nom::Err;
 /// # use nom::ErrorKind;
+/// # use nom::types::CompleteByteSlice;
 /// # fn main() {
 ///  named!(multi<&[u8], Vec<&[u8]> >, many1!( tag!( "abcd" ) ) );
 ///
@@ -302,8 +303,14 @@ macro_rules! many0(
 ///  let b = b"azerty";
 ///
 ///  let res = vec![&b"abcd"[..], &b"abcd"[..]];
-///  assert_eq!(multi(&a[..]),Ok((&b"efgh"[..], res)));
+///  assert_eq!(multi(&a[..]), Ok((&b"efgh"[..], res)));
 ///  assert_eq!(multi(&b[..]), Err(Err::Error(error_position!(&b[..], ErrorKind::Many1))));
+///
+///  named!(multi_complete<CompleteByteSlice, Vec<CompleteByteSlice> >, many1!( tag!( "abcd" ) ) );
+///  let c = CompleteByteSlice(b"abcdabcd");
+///
+///  let res = vec![CompleteByteSlice(b"abcd"), CompleteByteSlice(b"abcd")];
+///  assert_eq!(multi_complete(c), Ok((CompleteByteSlice(b""), res)));
 /// # }
 /// ```
 #[cfg(feature = "alloc")]
@@ -926,7 +933,7 @@ macro_rules! fold_many1(
           }
 
           match failure {
-            $crate::lib::std::option::Option::Some(e) => Err(Err::Error(e)),
+            $crate::lib::std::option::Option::Some(e) => Err(Err::Failure(e)),
             $crate::lib::std::option::Option::None    => match incomplete {
               $crate::lib::std::option::Option::Some(i) => $crate::need_more($i, i),
               $crate::lib::std::option::Option::None    => Ok((input, acc))
diff --git a/src/nom.rs b/src/nom.rs
index 3f28dbe..01c6f03 100644
--- a/src/nom.rs
+++ b/src/nom.rs
@@ -584,28 +584,28 @@ pub enum Endianness {
 /// if the parameter is nom::Endianness::Big, parse a big endian u16 integer,
 /// otherwise a little endian u16 integer
 #[macro_export]
-macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_u16($i) } else { le_u16($i) } } ););
+macro_rules! u16 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_u16($i) } else { $crate::le_u16($i) } } ););
 /// if the parameter is nom::Endianness::Big, parse a big endian u32 integer,
 /// otherwise a little endian u32 integer
 #[macro_export]
-macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_u32($i) } else { le_u32($i) } } ););
+macro_rules! u32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_u32($i) } else { $crate::le_u32($i) } } ););
 /// if the parameter is nom::Endianness::Big, parse a big endian u64 integer,
 /// otherwise a little endian u64 integer
 #[macro_export]
-macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_u64($i) } else { le_u64($i) } } ););
+macro_rules! u64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_u64($i) } else { $crate::le_u64($i) } } ););
 
 /// if the parameter is nom::Endianness::Big, parse a big endian i16 integer,
 /// otherwise a little endian i16 integer
 #[macro_export]
-macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_i16($i) } else { le_i16($i) } } ););
+macro_rules! i16 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_i16($i) } else { $crate::le_i16($i) } } ););
 /// if the parameter is nom::Endianness::Big, parse a big endian i32 integer,
 /// otherwise a little endian i32 integer
 #[macro_export]
-macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_i32($i) } else { le_i32($i) } } ););
+macro_rules! i32 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_i32($i) } else { $crate::le_i32($i) } } ););
 /// if the parameter is nom::Endianness::Big, parse a big endian i64 integer,
 /// otherwise a little endian i64 integer
 #[macro_export]
-macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { be_i64($i) } else { le_i64($i) } } ););
+macro_rules! i64 ( ($i:expr, $e:expr) => ( {if $crate::Endianness::Big == $e { $crate::be_i64($i) } else { $crate::le_i64($i) } } ););
 
 /// Recognizes big endian 4 bytes floating point number
 #[inline]
@@ -695,6 +695,17 @@ where
   Ok((input.slice(input.input_len()..), input))
 }
 
+/// Return the length of the remaining input.
+#[inline]
+pub fn rest_len<T>(input: T) -> IResult<T, usize>
+where
+  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+  T: InputLength,
+{
+  let len = input.input_len();
+  Ok((input, len))
+}
+
 /// Return the remaining input, for strings.
 #[inline]
 pub fn rest_s(input: &str) -> IResult<&str, &str> {
@@ -1316,6 +1327,12 @@ mod tests {
     assert_eq!(rest(input), Ok((empty, input)));
   }
 
+  #[test]
+  fn rest_len_on_slices() {
+    let input: &[u8] = &b"Hello, world!"[..];
+    assert_eq!(rest_len(input), Ok((input, input.len())));
+  }
+
   #[test]
   fn configurable_endianness() {
     named!(be_tst16<u16>, u16!(Endianness::Big));
diff --git a/src/util.rs b/src/util.rs
index cc1a73d..e1a5a48 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -490,6 +490,7 @@ pub enum ErrorKind<E = u32> {
   TakeTill1,
   TakeUntilAndConsume1,
   TakeWhileMN,
+  ParseTo,
 }
 
 #[cfg_attr(rustfmt, rustfmt_skip)]
@@ -557,6 +558,7 @@ pub fn error_to_u32<E>(e: &ErrorKind<E>) -> u32 {
     ErrorKind::TakeTill1                 => 67,
     ErrorKind::TakeUntilAndConsume1      => 68,
     ErrorKind::TakeWhileMN               => 69,
+    ErrorKind::ParseTo                   => 70,
   }
 }
 
@@ -626,6 +628,7 @@ impl<E> ErrorKind<E> {
       ErrorKind::TakeTill1                 => "TakeTill1",
       ErrorKind::TakeUntilAndConsume1      => "Take at least 1 until and consume",
       ErrorKind::TakeWhileMN               => "TakeWhileMN",
+      ErrorKind::ParseTo                   => "Parse string to the specified type",
     }
   }
 
@@ -707,6 +710,7 @@ impl<F, E: From<F>> Convert<ErrorKind<F>> for ErrorKind<E> {
       ErrorKind::TakeTill1                 => ErrorKind::TakeTill1,
       ErrorKind::TakeUntilAndConsume1      => ErrorKind::TakeUntilAndConsume1,
       ErrorKind::TakeWhileMN               => ErrorKind::TakeWhileMN,
+      ErrorKind::ParseTo                   => ErrorKind::ParseTo,
     }
   }
 }


Test patch:
diff --git a/tests/issues.rs b/tests/issues.rs
index 66d3753..0802747 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -6,7 +6,7 @@
 extern crate nom;
 extern crate regex;
 
-use nom::{space, Err, IResult, Needed, le_u64};
+use nom::{space, Err, IResult, Needed, le_u64, is_digit};
 use nom::types::{CompleteStr, CompleteByteSlice};
 
 #[allow(dead_code)]
@@ -255,6 +255,14 @@ named!(issue_741_str<CompleteStr, CompleteStr>, re_match!(r"^_?[A-Za-z][0-9A-Z_a
 named!(issue_741_bytes<CompleteByteSlice, CompleteByteSlice>, re_bytes_match!(r"^_?[A-Za-z][0-9A-Z_a-z-]*"));
 
 
+#[test]
+fn issue_752() {
+    assert_eq!(
+        Err::Error(nom::Context::Code("ab", nom::ErrorKind::ParseTo)),
+        parse_to!("ab", usize).unwrap_err(),
+    )
+}
+
 fn atom_specials(c: u8) -> bool {
     c == b'q'
 }
@@ -272,3 +280,50 @@ fn issue_759() {
 named_args!(issue_771(count: usize)<Vec<u32>>,
   length_count!(value!(count), call!(nom::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::alpha), '\\', 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::{Err,be_f64};
+  pub type Input<'a> = &'a [u8];
+
+  #[derive(PartialEq, Debug, Clone)]
+  struct Data {
+      c: f64,
+      v: Vec<f64>
+  }
+
+  fn list<'a,'b>(input: Input<'a>, _cs: &'b f64) -> Result<(Input<'a>,Vec<f64>), Err<&'a [u8]>> {
+      separated_list_complete!(input, tag!(","),be_f64)
+  }
+
+  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
+          }
+      }
+  ));
+}
+
+named!(issue_775, take_till1!(|_| true));