Repository: rust-bakery/nom (language: rust)

Issue:
not_line_ending fails with lone '\r' but doesn't document this
Rust version: 1.48.0
nom version: 6.0.1

The documentation of `nom::character::complete::not_line_ending` states that it

> Recognizes a string of any char except '\r' or '\n'.

In fact, if the input has a carriage feed ('\r') not followed by a line break ('\n') the parser fails, even if it subsequently followed by a valid line break:

```
extern crate nom;

use nom::IResult;

fn not_line_ending(s: &str) -> IResult<&str, &str> {
    nom::character::complete::not_line_ending(s)
}

fn main() {
    assert_eq!(not_line_ending("xxx\ry\nz"), Ok(("\ry\nz", "xxx")));
    // Actual result: Err(Error(Error {input: "xxx\ry\nz", code: Tag}))
}
```

Of course, a lone '\r' in a string is badly formed text and it makes sense to treat it as exceptional. Since the behavior that implemented is more complicated than the behavior that was documented I expect it is deliberate. If that's the case the documentation should be updated.


Discussion / hints:

Fix patch:
diff --git a/src/character/complete.rs b/src/character/complete.rs
index b0d6274cd..cbcff46df 100644
--- a/src/character/complete.rs
+++ b/src/character/complete.rs
@@ -151,21 +151,24 @@ where
 }
 
 //FIXME: there's still an incomplete
-/// Recognizes a string of any char except '\r' or '\n'.
+/// Recognizes a string of any char except '\r\n' or '\n'.
 ///
 /// *Complete version*: Will return an error if there's not enough input data.
 /// # Example
 ///
 /// ```
-/// # use nom::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed};
 /// # use nom::character::complete::not_line_ending;
 /// fn parser(input: &str) -> IResult<&str, &str> {
 ///     not_line_ending(input)
 /// }
 ///
 /// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab")));
+/// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab")));
 /// assert_eq!(parser("abc"), Ok(("", "abc")));
 /// assert_eq!(parser(""), Ok(("", "")));
+/// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag })));
+/// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag })));
 /// ```
 pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
 where
diff --git a/src/character/streaming.rs b/src/character/streaming.rs
index c685b6ffc..4c33ee9fd 100644
--- a/src/character/streaming.rs
+++ b/src/character/streaming.rs
@@ -151,17 +151,19 @@ where
   }
 }
 
-/// Recognizes a string of any char except '\r' or '\n'.
+/// Recognizes a string of any char except '\r\n' or '\n'.
 ///
 /// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data.
 /// # Example
 ///
 /// ```
-/// # use nom::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed};
 /// # use nom::character::streaming::not_line_ending;
 /// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Ok(("\r\nc", "ab")));
 /// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("abc"), Err(Err::Incomplete(Needed::Unknown)));
 /// assert_eq!(not_line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rb\nc"), Err(Err::Error(("a\rb\nc", ErrorKind::Tag ))));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rbc"), Err(Err::Error(("a\rbc", ErrorKind::Tag ))));
 /// ```
 pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
 where


Test patch: