Repository: Geal/nom
Pull request #774 (2018-05-19 11:24:11)

Add pcap parser to the "network protocol formats" list
As stated in the title, this simply add the pcap parser I made to the Readme file.

It may require to check to corresponding box on #14.

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

Coverage remained the same at 87.566% when pulling **105ef295f9e5d616fc1e56009354678968ffa447 on ithinuel:add-pcap-parser** into **64af2d1cac7298b511eb671163dcdbb2ad197d17 on Geal:master**.

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

Coverage remained the same at 87.566% when pulling **105ef295f9e5d616fc1e56009354678968ffa447 on ithinuel:add-pcap-parser** into **64af2d1cac7298b511eb671163dcdbb2ad197d17 on Geal:master**.


Patch:
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_2.md b/doc/upgrading_to_nom_2.md
index 0eb2abc..b60b908 100644
--- a/doc/upgrading_to_nom_2.md
+++ b/doc/upgrading_to_nom_2.md
@@ -106,7 +106,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 +133,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..76c2b13 100644
--- a/doc/upgrading_to_nom_4.md
+++ b/doc/upgrading_to_nom_4.md
@@ -231,10 +231,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 c1e571f..66725e6 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -150,6 +150,33 @@ 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]
 macro_rules! named_args {
     (pub $func_name:ident ( $( $arg:ident : $typ:ty ),* ) < $return_type:ty > , $submac:ident!( $($args:tt)* ) ) => {
@@ -671,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>)))
       }
     }
   );
@@ -950,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)*) {
@@ -1517,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..1c59d04 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,13 @@ 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))));
+///
+///  let c = CompleteByteSlice(b"abcdabcd");
+///
+///  let res = vec![CompleteByteSlice(b"abcd"), CompleteByteSlice(b"abcd")];
+///  assert_eq!(multi(c), Ok((CompleteByteSlice(b""), res)));
 /// # }
 /// ```
 #[cfg(feature = "alloc")]
@@ -926,7 +932,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..588e54d 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -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,12 @@ 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"))
+  );
+}