summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/src/ascii/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/winnow/src/ascii/tests.rs')
-rw-r--r--vendor/winnow/src/ascii/tests.rs1496
1 files changed, 1496 insertions, 0 deletions
diff --git a/vendor/winnow/src/ascii/tests.rs b/vendor/winnow/src/ascii/tests.rs
new file mode 100644
index 000000000..b715d0920
--- /dev/null
+++ b/vendor/winnow/src/ascii/tests.rs
@@ -0,0 +1,1496 @@
+use super::*;
+
+mod complete {
+ use super::*;
+ use crate::combinator::alt;
+ use crate::combinator::opt;
+ use crate::error::ErrMode;
+ use crate::error::Error;
+ use crate::error::ErrorKind;
+ use crate::stream::ParseSlice;
+ use crate::token::none_of;
+ use crate::token::one_of;
+ #[cfg(feature = "alloc")]
+ use crate::{lib::std::string::String, lib::std::vec::Vec};
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, Error<_>> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn character() {
+ let empty: &[u8] = b"";
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, Error>(a), Err(ErrMode::Incomplete(Needed::Size(1))));
+ assert_parse!(alpha1(a), Ok((empty, a)));
+ assert_eq!(
+ alpha1(b),
+ Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Slice)))
+ );
+ assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], &b"a"[..])));
+ assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12".as_bytes(), &b"az"[..])));
+ assert_eq!(
+ digit1(a),
+ Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Slice)))
+ );
+ assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(
+ digit1(c),
+ Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ digit1(d),
+ Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Slice)))
+ );
+ assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c)));
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(d),
+ Ok(("zé12".as_bytes(), &b"a"[..]))
+ );
+ assert_eq!(
+ hex_digit1(e),
+ Err(ErrMode::Backtrack(Error::new(e, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ oct_digit1(a),
+ Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Slice)))
+ );
+ assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(
+ oct_digit1(c),
+ Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ oct_digit1(d),
+ Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Slice)))
+ );
+ assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c)));
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e)));
+ assert_eq!(space1::<_, Error<_>>(f), Ok((&b";"[..], &b" "[..])));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let empty = "";
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(alpha1::<_, Error<_>>(a), Ok((empty, a)));
+ assert_eq!(
+ alpha1(b),
+ Err(ErrMode::Backtrack(Error::new(b, ErrorKind::Slice)))
+ );
+ assert_eq!(alpha1::<_, Error<_>>(c), Ok((&c[1..], "a")));
+ assert_eq!(alpha1::<_, Error<_>>(d), Ok(("é12", "az")));
+ assert_eq!(
+ digit1(a),
+ Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Slice)))
+ );
+ assert_eq!(digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(
+ digit1(c),
+ Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ digit1(d),
+ Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Slice)))
+ );
+ assert_eq!(hex_digit1::<_, Error<_>>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, Error<_>>(c), Ok((empty, c)));
+ assert_eq!(hex_digit1::<_, Error<_>>(d), Ok(("zé12", "a")));
+ assert_eq!(
+ hex_digit1(e),
+ Err(ErrMode::Backtrack(Error::new(e, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ oct_digit1(a),
+ Err(ErrMode::Backtrack(Error::new(a, ErrorKind::Slice)))
+ );
+ assert_eq!(oct_digit1::<_, Error<_>>(b), Ok((empty, b)));
+ assert_eq!(
+ oct_digit1(c),
+ Err(ErrMode::Backtrack(Error::new(c, ErrorKind::Slice)))
+ );
+ assert_eq!(
+ oct_digit1(d),
+ Err(ErrMode::Backtrack(Error::new(d, ErrorKind::Slice)))
+ );
+ assert_eq!(alphanumeric1::<_, Error<_>>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, Error<_>>(c), Ok((empty, c)));
+ assert_eq!(alphanumeric1::<_, Error<_>>(d), Ok(("é12", "az")));
+ assert_eq!(space1::<_, Error<_>>(e), Ok((empty, e)));
+ }
+
+ use crate::stream::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, Error<_>>(a) {
+ Ok((i, _)) => {
+ assert_eq!(a.offset_to(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, Error<_>>(b) {
+ Ok((i, _)) => {
+ assert_eq!(b.offset_to(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, Error<_>>(c) {
+ Ok((i, _)) => {
+ assert_eq!(c.offset_to(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, Error<_>>(d) {
+ Ok((i, _)) => {
+ assert_eq!(d.offset_to(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, Error<_>>(e) {
+ Ok((i, _)) => {
+ assert_eq!(e.offset_to(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, Error<_>>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset_to(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, Error<_>>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset_to(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(a),
+ Ok((&b"\nefgh"[..], &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(b),
+ Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(c),
+ Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(not_line_ending::<_, Error<_>>(d), Ok((&[][..], d)));
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(
+ not_line_ending(f),
+ Err(ErrMode::Backtrack(Error::new(f, ErrorKind::Tag)))
+ );
+
+ let g2: &str = "ab12cd";
+ assert_eq!(not_line_ending::<_, Error<_>>(g2), Ok(("", g2)));
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(ErrMode::Backtrack(error_position!(i, ErrorKind::Slice)))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(ErrMode::Backtrack(error_position!(i, ErrorKind::Slice)))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(i),
+ Err(ErrMode::Backtrack(error_position!(i, ErrorKind::Slice)))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ (not_line_ending, line_ending).parse_next(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
+ }
+
+ #[test]
+ fn full_line_unix() {
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ (not_line_ending, line_ending).parse_next(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ crlf(&b"\r"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b"\r"[..],
+ ErrorKind::Tag
+ )))
+ );
+ assert_parse!(
+ crlf(&b"\ra"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b"\ra"[..],
+ ErrorKind::Tag
+ )))
+ );
+
+ assert_parse!(crlf("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ crlf("\r"),
+ Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::Tag)))
+ );
+ assert_parse!(
+ crlf("\ra"),
+ Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::Tag)))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..])));
+ assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ line_ending(&b"\r"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b"\r"[..],
+ ErrorKind::Tag
+ )))
+ );
+ assert_parse!(
+ line_ending(&b"\ra"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b"\ra"[..],
+ ErrorKind::Tag
+ )))
+ );
+
+ assert_parse!(line_ending("\na"), Ok(("a", "\n")));
+ assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ line_ending("\r"),
+ Err(ErrMode::Backtrack(error_position!("\r", ErrorKind::Tag)))
+ );
+ assert_parse!(
+ line_ending("\ra"),
+ Err(ErrMode::Backtrack(error_position!("\ra", ErrorKind::Tag)))
+ );
+ }
+
+ fn digit_to_i16(input: &str) -> IResult<&str, i16> {
+ let i = input;
+ let (i, opt_sign) = opt(alt(('+', '-'))).parse_next(i)?;
+ let sign = match opt_sign {
+ Some('+') | None => true,
+ Some('-') => false,
+ _ => unreachable!(),
+ };
+
+ let (i, s) = digit1::<_, crate::error::Error<_>>(i)?;
+ match s.parse_slice() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(ErrMode::from_error_kind(i, ErrorKind::Verify)),
+ }
+ }
+
+ fn digit_to_u32(i: &str) -> IResult<&str, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_slice() {
+ Some(n) => Ok((i, n)),
+ None => Err(ErrMode::from_error_kind(i, ErrorKind::Verify)),
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(&s);
+ let res2 = dec_int(s.as_str());
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(&s);
+ let res2 = dec_uint(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+
+ #[test]
+ fn hex_uint_tests() {
+ fn hex_u32(input: &[u8]) -> IResult<&[u8], u32> {
+ hex_uint(input)
+ }
+
+ assert_parse!(
+ hex_u32(&b";"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b";"[..],
+ ErrorKind::Slice
+ )))
+ );
+ assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255)));
+ assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138)));
+ assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(
+ hex_u32(&b"00c5a31be2;"[..]), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ &b"00c5a31be2;"[..],
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(&b"c5a31be201;"[..]), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ &b"c5a31be201;"[..],
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295)));
+ assert_parse!(
+ hex_u32(&b"ffffffffffffffff;"[..]), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ &b"ffffffffffffffff;"[..],
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(&b"ffffffffffffffff"[..]), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ &b"ffffffffffffffff"[..],
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0)));
+ assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af)));
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn float_test() {
+ let mut test_cases = vec![
+ "+3.14",
+ "3.14",
+ "-3.14",
+ "0",
+ "0.0",
+ "1.",
+ ".789",
+ "-.5",
+ "1e7",
+ "-1E-7",
+ ".3e-2",
+ "1.e4",
+ "1.2e4",
+ "12.34",
+ "-1.234E-12",
+ "-1.234e-12",
+ "0.00000000000000000087",
+ ];
+
+ for test in test_cases.drain(..) {
+ let expected32 = str::parse::<f32>(test).unwrap();
+ let expected64 = str::parse::<f64>(test).unwrap();
+
+ println!("now parsing: {} -> {}", test, expected32);
+
+ let larger = test.to_string();
+
+ assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32)));
+ assert_parse!(float(&larger[..]), Ok(("", expected32)));
+
+ assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected64)));
+ assert_parse!(float(&larger[..]), Ok(("", expected64)));
+ }
+
+ let remaining_exponent = "-1.234E-";
+ assert_parse!(
+ float::<_, f64, _>(remaining_exponent),
+ Err(ErrMode::Cut(Error {
+ input: "",
+ kind: ErrorKind::Slice
+ }))
+ );
+
+ let (_i, nan) = float::<_, f32, ()>("NaN").unwrap();
+ assert!(nan.is_nan());
+
+ let (_i, inf) = float::<_, f32, ()>("inf").unwrap();
+ assert!(inf.is_infinite());
+ let (_i, inf) = float::<_, f32, ()>("infinite").unwrap();
+ assert!(inf.is_infinite());
+ }
+
+ #[cfg(feature = "std")]
+ fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
+ #[allow(deprecated)] // will just become `pub(crate)` later
+ match super::recognize_float_or_exceptions(i) {
+ Err(e) => Err(e),
+ Ok((i, s)) => {
+ if s.is_empty() {
+ return Err(ErrMode::Backtrack(()));
+ }
+ match s.parse_slice() {
+ Some(n) => Ok((i, n)),
+ None => Err(ErrMode::Backtrack(())),
+ }
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg(feature = "std")]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn floats(s in "\\PC*") {
+ println!("testing {}", s);
+ let res1 = parse_f64(&s);
+ let res2 = float::<_, f64, ()>(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+
+ // issue #1336 "escaped hangs if normal parser accepts empty"
+ #[test]
+ fn complete_escaped_hang() {
+ // issue #1336 "escaped hangs if normal parser accepts empty"
+ fn escaped_string(input: &str) -> IResult<&str, &str> {
+ use crate::ascii::alpha0;
+ use crate::token::one_of;
+ escaped(alpha0, '\\', one_of("n")).parse_next(input)
+ }
+
+ escaped_string("7").unwrap();
+ escaped_string("a7").unwrap();
+ }
+
+ #[test]
+ fn complete_escaped_hang_1118() {
+ // issue ##1118 escaped does not work with empty string
+ fn unquote(input: &str) -> IResult<&str, &str> {
+ use crate::combinator::delimited;
+ use crate::combinator::opt;
+ use crate::token::one_of;
+
+ delimited(
+ '"',
+ escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
+ '"',
+ )
+ .parse_next(input)
+ }
+
+ assert_eq!(unquote(r#""""#), Ok(("", "")));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[allow(unused_variables)]
+ #[test]
+ fn complete_escaping() {
+ use crate::ascii::{alpha1 as alpha, digit1 as digit};
+ use crate::token::one_of;
+
+ fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(alpha, '\\', one_of("\"n\\")).parse_next(i)
+ }
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
+ assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
+ assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
+ assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b""[..],
+ ErrorKind::Token
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(ErrMode::Backtrack(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::Token,
+ error_position!(&b"A"[..], ErrorKind::Verify)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(digit, '\\', one_of("\"n\\")).parse_next(i)
+ }
+ assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn complete_escaping_str() {
+ use crate::ascii::{alpha1 as alpha, digit1 as digit};
+ use crate::token::one_of;
+
+ fn esc(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\\', one_of("\"n\\")).parse_next(i)
+ }
+ assert_eq!(esc("abcd;"), Ok((";", "abcd")));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
+ assert_eq!(esc("\\n;"), Ok((";", "\\n")));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
+ assert_eq!(
+ esc("AB\\"),
+ Err(ErrMode::Backtrack(error_position!("", ErrorKind::Token)))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(ErrMode::Backtrack(error_node_position!(
+ "AB\\A",
+ ErrorKind::Token,
+ error_position!("A", ErrorKind::Verify)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, &str> {
+ escaped(digit, '\\', one_of("\"n\\")).parse_next(i)
+ }
+ assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));
+
+ fn esc3(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\u{241b}', one_of("\"n")).parse_next(i)
+ }
+ assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
+ }
+
+ #[test]
+ fn test_escaped_error() {
+ fn esc(s: &str) -> IResult<&str, &str> {
+ use crate::ascii::digit1;
+ escaped(digit1, '\\', one_of("\"n\\")).parse_next(s)
+ }
+
+ assert_eq!(esc("abcd"), Ok(("abcd", "")));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn complete_escape_transform() {
+ use crate::ascii::alpha1 as alpha;
+
+ #[cfg(feature = "alloc")]
+ fn to_s(i: Vec<u8>) -> String {
+ String::from_utf8_lossy(&i).into_owned()
+ }
+
+ fn esc(i: &[u8]) -> IResult<&[u8], String> {
+ escaped_transform(
+ alpha,
+ '\\',
+ alt((
+ "\\".value(&b"\\"[..]),
+ "\"".value(&b"\""[..]),
+ "n".value(&b"\n"[..]),
+ )),
+ )
+ .map(to_s)
+ .parse_next(i)
+ }
+
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
+ assert_eq!(
+ esc(&b"ab\\\"cd;"[..]),
+ Ok((&b";"[..], String::from("ab\"cd")))
+ );
+ assert_eq!(
+ esc(&b"\\\"abcd;"[..]),
+ Ok((&b";"[..], String::from("\"abcd")))
+ );
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
+ assert_eq!(
+ esc(&b"ab\\\"12"[..]),
+ Ok((&b"12"[..], String::from("ab\"")))
+ );
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(ErrMode::Backtrack(error_position!(
+ &b""[..],
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(ErrMode::Backtrack(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::Eof,
+ error_position!(&b"A"[..], ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], String> {
+ escaped_transform(
+ alpha,
+ '&',
+ alt((
+ "egrave;".value("è".as_bytes()),
+ "agrave;".value("à".as_bytes()),
+ )),
+ )
+ .map(to_s)
+ .parse_next(i)
+ }
+ assert_eq!(
+ esc2(&b"ab&egrave;DEF;"[..]),
+ Ok((&b";"[..], String::from("abèDEF")))
+ );
+ assert_eq!(
+ esc2(&b"ab&egrave;D&agrave;EF;"[..]),
+ Ok((&b";"[..], String::from("abèDàEF")))
+ );
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn complete_escape_transform_str() {
+ use crate::ascii::alpha1 as alpha;
+
+ fn esc(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '\\',
+ alt(("\\".value("\\"), "\"".value("\""), "n".value("\n"))),
+ )
+ .parse_next(i)
+ }
+
+ assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
+ assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
+ assert_eq!(
+ esc("AB\\"),
+ Err(ErrMode::Backtrack(error_position!("", ErrorKind::Tag)))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(ErrMode::Backtrack(error_node_position!(
+ "AB\\A",
+ ErrorKind::Eof,
+ error_position!("A", ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '&',
+ alt(("egrave;".value("è"), "agrave;".value("à"))),
+ )
+ .parse_next(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")))
+ );
+
+ fn esc3(i: &str) -> IResult<&str, String> {
+ escaped_transform(alpha, '␛', alt(("0".value("\0"), "n".value("\n")))).parse_next(i)
+ }
+ assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn test_escaped_transform_error() {
+ fn esc_trans(s: &str) -> IResult<&str, String> {
+ use crate::ascii::digit1;
+ escaped_transform(digit1, '\\', "n").parse_next(s)
+ }
+
+ assert_eq!(esc_trans("abcd"), Ok(("abcd", String::new())));
+ }
+}
+
+mod partial {
+ use super::*;
+ use crate::combinator::opt;
+ use crate::error::Error;
+ use crate::error::ErrorKind;
+ use crate::error::{ErrMode, Needed};
+ use crate::stream::ParseSlice;
+ use crate::IResult;
+ use crate::Partial;
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, Error<_>> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn character() {
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, Error<_>>(a), Err(ErrMode::Incomplete(Needed::new(1))));
+ assert_parse!(
+ alpha1(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alpha1(Partial::new(b)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(b),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ alpha1::<_, Error<_>>(Partial::new(c)),
+ Ok((Partial::new(&c[1..]), &b"a"[..]))
+ );
+ assert_eq!(
+ alpha1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("é12".as_bytes()), &b"az"[..]))
+ );
+ assert_eq!(
+ digit1(Partial::new(a)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(a),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ digit1(Partial::new(c)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(c),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ digit1(Partial::new(d)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(d),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(c)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("zé12".as_bytes()), &b"a"[..]))
+ );
+ assert_eq!(
+ hex_digit1(Partial::new(e)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(e),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(a)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(a),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(c)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(c),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(d)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(d),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(c)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("é12".as_bytes()), &b"az"[..]))
+ );
+ assert_eq!(
+ space1::<_, Error<_>>(Partial::new(e)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ space1::<_, Error<_>>(Partial::new(f)),
+ Ok((Partial::new(&b";"[..]), &b" "[..]))
+ );
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(
+ alpha1::<_, Error<_>>(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alpha1(Partial::new(b)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(b),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ alpha1::<_, Error<_>>(Partial::new(c)),
+ Ok((Partial::new(&c[1..]), "a"))
+ );
+ assert_eq!(
+ alpha1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("é12"), "az"))
+ );
+ assert_eq!(
+ digit1(Partial::new(a)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(a),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ digit1(Partial::new(c)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(c),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ digit1(Partial::new(d)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(d),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(c)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("zé12"), "a"))
+ );
+ assert_eq!(
+ hex_digit1(Partial::new(e)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(e),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(a)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(a),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1::<_, Error<_>>(Partial::new(b)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(c)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(c),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ oct_digit1(Partial::new(d)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(d),
+ ErrorKind::Slice
+ )))
+ );
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(a)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(c)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, Error<_>>(Partial::new(d)),
+ Ok((Partial::new("é12"), "az"))
+ );
+ assert_eq!(
+ space1::<_, Error<_>>(Partial::new(e)),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ }
+
+ use crate::stream::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, Error<_>>(Partial::new(a)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(a.offset_to(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, Error<_>>(Partial::new(b)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(b.offset_to(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, Error<_>>(Partial::new(c)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(c.offset_to(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, Error<_>>(Partial::new(d)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(d.offset_to(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, Error<_>>(Partial::new(e)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(e.offset_to(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, Error<_>>(Partial::new(f)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(f.offset_to(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, Error<_>>(Partial::new(f)) {
+ Ok((i, _)) => {
+ let i = i.into_inner();
+ assert_eq!(f.offset_to(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(Partial::new(a)),
+ Ok((Partial::new(&b"\nefgh"[..]), &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(Partial::new(b)),
+ Ok((Partial::new(&b"\nefgh\nijkl"[..]), &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(Partial::new(c)),
+ Ok((Partial::new(&b"\r\nefgh\nijkl"[..]), &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(Partial::new(d)),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(
+ not_line_ending(Partial::new(f)),
+ Err(ErrMode::Backtrack(Error::new(
+ Partial::new(f),
+ ErrorKind::Tag
+ )))
+ );
+
+ let g2: &str = "ab12cd";
+ assert_eq!(
+ not_line_ending::<_, Error<_>>(Partial::new(g2)),
+ Err(ErrMode::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(
+ hex_digit1(Partial::new(i)),
+ Ok((Partial::new(&b";"[..]), &i[..i.len() - 1]))
+ );
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(Partial::new(i)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(i),
+ ErrorKind::Slice
+ )))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(Partial::new(i)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(i),
+ ErrorKind::Slice
+ )))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(
+ oct_digit1(Partial::new(i)),
+ Ok((Partial::new(&b";"[..]), &i[..i.len() - 1]))
+ );
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(Partial::new(i)),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(i),
+ ErrorKind::Slice
+ )))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ #[allow(clippy::type_complexity)]
+ fn take_full_line(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (&[u8], &[u8])> {
+ (not_line_ending, line_ending).parse_next(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(Partial::new(input));
+ assert_eq!(
+ output,
+ Ok((Partial::new(&b""[..]), (&b"abc"[..], &b"\r\n"[..])))
+ );
+ }
+
+ #[test]
+ fn full_line_unix() {
+ #[allow(clippy::type_complexity)]
+ fn take_full_line(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (&[u8], &[u8])> {
+ (not_line_ending, line_ending).parse_next(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(Partial::new(input));
+ assert_eq!(
+ output,
+ Ok((Partial::new(&b""[..]), (&b"abc"[..], &b"\n"[..])))
+ );
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(Partial::new(&input[..]));
+ assert_parse!(output, Ok((Partial::new(&b""[..]), &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(Partial::new(&input[..]));
+ assert_parse!(output, Ok((Partial::new(&b""[..]), &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(
+ crlf(Partial::new(&b"\r\na"[..])),
+ Ok((Partial::new(&b"a"[..]), &b"\r\n"[..]))
+ );
+ assert_parse!(
+ crlf(Partial::new(&b"\r"[..])),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_parse!(
+ crlf(Partial::new(&b"\ra"[..])),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"\ra"[..]),
+ ErrorKind::Tag
+ )))
+ );
+
+ assert_parse!(crlf(Partial::new("\r\na")), Ok((Partial::new("a"), "\r\n")));
+ assert_parse!(
+ crlf(Partial::new("\r")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_parse!(
+ crlf(Partial::new("\ra")),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new("\ra"),
+ ErrorKind::Tag
+ )))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(
+ line_ending(Partial::new(&b"\na"[..])),
+ Ok((Partial::new(&b"a"[..]), &b"\n"[..]))
+ );
+ assert_parse!(
+ line_ending(Partial::new(&b"\r\na"[..])),
+ Ok((Partial::new(&b"a"[..]), &b"\r\n"[..]))
+ );
+ assert_parse!(
+ line_ending(Partial::new(&b"\r"[..])),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_parse!(
+ line_ending(Partial::new(&b"\ra"[..])),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"\ra"[..]),
+ ErrorKind::Tag
+ )))
+ );
+
+ assert_parse!(
+ line_ending(Partial::new("\na")),
+ Ok((Partial::new("a"), "\n"))
+ );
+ assert_parse!(
+ line_ending(Partial::new("\r\na")),
+ Ok((Partial::new("a"), "\r\n"))
+ );
+ assert_parse!(
+ line_ending(Partial::new("\r")),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ assert_parse!(
+ line_ending(Partial::new("\ra")),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new("\ra"),
+ ErrorKind::Tag
+ )))
+ );
+ }
+
+ fn digit_to_i16(input: Partial<&str>) -> IResult<Partial<&str>, i16> {
+ let i = input;
+ let (i, opt_sign) = opt(one_of("+-")).parse_next(i)?;
+ let sign = match opt_sign {
+ Some('+') | None => true,
+ Some('-') => false,
+ _ => unreachable!(),
+ };
+
+ let (i, s) = digit1::<_, crate::error::Error<_>>(i)?;
+ match s.parse_slice() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(ErrMode::from_error_kind(i, ErrorKind::Verify)),
+ }
+ }
+
+ fn digit_to_u32(i: Partial<&str>) -> IResult<Partial<&str>, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_slice() {
+ Some(n) => Ok((i, n)),
+ None => Err(ErrMode::from_error_kind(i, ErrorKind::Verify)),
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(Partial::new(&s));
+ let res2 = dec_int(Partial::new(s.as_str()));
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(Partial::new(&s));
+ let res2 = dec_uint(Partial::new(s.as_str()));
+ assert_eq!(res1, res2);
+ }
+ }
+
+ #[test]
+ fn hex_uint_tests() {
+ fn hex_u32(input: Partial<&[u8]>) -> IResult<Partial<&[u8]>, u32> {
+ hex_uint(input)
+ }
+
+ assert_parse!(
+ hex_u32(Partial::new(&b";"[..])),
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b";"[..]),
+ ErrorKind::Slice
+ )))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"ff;"[..])),
+ Ok((Partial::new(&b";"[..]), 255))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"1be2;"[..])),
+ Ok((Partial::new(&b";"[..]), 7138))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"c5a31be2;"[..])),
+ Ok((Partial::new(&b";"[..]), 3_315_801_058))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"C5A31be2;"[..])),
+ Ok((Partial::new(&b";"[..]), 3_315_801_058))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"00c5a31be2;"[..])), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"00c5a31be2;"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"c5a31be201;"[..])), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"c5a31be201;"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"ffffffff;"[..])),
+ Ok((Partial::new(&b";"[..]), 4_294_967_295))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"ffffffffffffffff;"[..])), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"ffffffffffffffff;"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"ffffffffffffffff"[..])), // overflow
+ Err(ErrMode::Backtrack(error_position!(
+ Partial::new(&b"ffffffffffffffff"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"0x1be2;"[..])),
+ Ok((Partial::new(&b"x1be2;"[..]), 0))
+ );
+ assert_parse!(
+ hex_u32(Partial::new(&b"12af"[..])),
+ Err(ErrMode::Incomplete(Needed::new(1)))
+ );
+ }
+}