use super::*; #[cfg(feature = "std")] use proptest::prelude::*; use snapbox::prelude::*; use snapbox::str; use crate::ascii::Caseless; use crate::combinator::delimited; use crate::error::ErrMode; use crate::error::InputError; use crate::prelude::*; use crate::stream::AsChar; use crate::token::literal; use crate::Partial; #[test] fn complete_take_while_m_n_utf8_all_matching() { assert_parse!( take_while(1..=4, |c: char| c.is_alphabetic()).parse_peek("øn"), str![[r#" Ok( ( "", "øn", ), ) "#]] .raw() ); } #[test] fn complete_take_while_m_n_utf8_all_matching_substring() { assert_parse!( take_while(1, |c: char| c.is_alphabetic()).parse_peek("øn"), str![[r#" Ok( ( "n", "ø", ), ) "#]] .raw() ); } #[cfg(feature = "std")] proptest! { #[test] #[cfg_attr(miri, ignore)] // See https://github.com/AltSysrq/proptest/issues/253 fn complete_take_while_m_n_bounds(m in 0..20usize, n in 0..20usize, valid in 0..20usize, invalid in 0..20usize) { let input = format!("{:a( m: usize, n: usize, valid: usize, input: &mut &'i str, ) -> ModalResult<&'i str> { if n < m { Err(crate::error::ParserError::from_input(input)) } else if m <= valid { let offset = n.min(valid); Ok(input.next_slice(offset)) } else { Err(crate::error::ParserError::from_input(input)) } } #[test] fn complete_take_until() { fn take_until_5_10<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> { take_until(5..=8, "end").parse_next(i) } assert_parse!( take_until_5_10.parse_peek("end"), str![[r#" Err( Backtrack( InputError { input: "end", }, ), ) "#]] .raw() ); assert_parse!( take_until_5_10.parse_peek("1234end"), str![[r#" Err( Backtrack( InputError { input: "1234end", }, ), ) "#]] .raw() ); assert_parse!( take_until_5_10.parse_peek("12345end"), str![[r#" Ok( ( "end", "12345", ), ) "#]] .raw() ); assert_parse!( take_until_5_10.parse_peek("123456end"), str![[r#" Ok( ( "end", "123456", ), ) "#]] .raw() ); assert_parse!( take_until_5_10.parse_peek("12345678end"), str![[r#" Ok( ( "end", "12345678", ), ) "#]] .raw() ); assert_parse!( take_until_5_10.parse_peek("123456789end"), str![[r#" Err( Backtrack( InputError { input: "123456789end", }, ), ) "#]] .raw() ); } #[test] fn complete_take_until_empty() { fn take_until_empty<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> { take_until(0, "").parse_next(i) } assert_parse!( take_until_empty.parse_peek(""), str![[r#" Ok( ( "", "", ), ) "#]] .raw() ); assert_parse!( take_until_empty.parse_peek("end"), str![[r#" Ok( ( "end", "", ), ) "#]] .raw() ); } #[test] fn complete_literal_case_insensitive() { fn caseless_bytes<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> { literal(Caseless("ABcd")).parse_next(i) } assert_parse!( caseless_bytes.parse_peek(&b"aBCdefgh"[..]), str![[r#" Ok( ( [ 101, 102, 103, 104, ], [ 97, 66, 67, 100, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(&b"abcdefgh"[..]), str![[r#" Ok( ( [ 101, 102, 103, 104, ], [ 97, 98, 99, 100, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(&b"ABCDefgh"[..]), str![[r#" Ok( ( [ 101, 102, 103, 104, ], [ 65, 66, 67, 68, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(&b"ab"[..]), str![[r#" Err( Backtrack( InputError { input: [ 97, 98, ], }, ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(&b"Hello"[..]), str![[r#" Err( Backtrack( InputError { input: [ 72, 101, 108, 108, 111, ], }, ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(&b"Hel"[..]), str![[r#" Err( Backtrack( InputError { input: [ 72, 101, 108, ], }, ), ) "#]] .raw() ); fn caseless_str<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> { literal(Caseless("ABcd")).parse_next(i) } assert_parse!( caseless_str.parse_peek("aBCdefgh"), str![[r#" Ok( ( "efgh", "aBCd", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek("abcdefgh"), str![[r#" Ok( ( "efgh", "abcd", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek("ABCDefgh"), str![[r#" Ok( ( "efgh", "ABCD", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek("ab"), str![[r#" Err( Backtrack( InputError { input: "ab", }, ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek("Hello"), str![[r#" Err( Backtrack( InputError { input: "Hello", }, ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek("Hel"), str![[r#" Err( Backtrack( InputError { input: "Hel", }, ), ) "#]] .raw() ); fn matches_kelvin<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> { literal(Caseless("k")).parse_next(i) } assert_parse!( matches_kelvin.parse_peek("K"), str![[r#" Err( Backtrack( InputError { input: "K", }, ), ) "#]] .raw() ); fn is_kelvin<'i>(i: &mut &'i str) -> TestResult<&'i str, &'i str> { literal(Caseless("K")).parse_next(i) } assert_parse!( is_kelvin.parse_peek("k"), str![[r#" Err( Backtrack( InputError { input: "k", }, ), ) "#]] .raw() ); } #[test] fn complete_literal_fixed_size_array() { fn test<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> { literal([0x42]).parse_next(i) } fn test2<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> { literal(&[0x42]).parse_next(i) } let input = &[0x42, 0x00][..]; assert_parse!( test.parse_peek(input), str![[r#" Ok( ( [ 0, ], [ 66, ], ), ) "#]] .raw() ); assert_parse!( test2.parse_peek(input), str![[r#" Ok( ( [ 0, ], [ 66, ], ), ) "#]] .raw() ); } #[test] fn complete_literal_char() { fn test<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> { literal('B').parse_next(i) } assert_parse!( test.parse_peek(&[0x42, 0x00][..]), str![[r#" Ok( ( [ 0, ], [ 66, ], ), ) "#]] .raw() ); assert_parse!( test.parse_peek(&[b'A', b'\0'][..]), str![[r#" Err( Backtrack( InputError { input: [ 65, 0, ], }, ), ) "#]] .raw() ); } #[test] fn complete_literal_byte() { fn test<'i>(i: &mut &'i [u8]) -> TestResult<&'i [u8], &'i [u8]> { literal(b'B').parse_next(i) } assert_parse!( test.parse_peek(&[0x42, 0x00][..]), str![[r#" Ok( ( [ 0, ], [ 66, ], ), ) "#]] .raw() ); assert_parse!( test.parse_peek(&[b'A', b'\0'][..]), str![[r#" Err( Backtrack( InputError { input: [ 65, 0, ], }, ), ) "#]] .raw() ); } #[test] fn partial_any_str() { use super::any; assert_parse!( any.parse_peek(Partial::new("Ә")), str![[r#" Ok( ( Partial { input: "", partial: true, }, 'Ә', ), ) "#]] .raw() ); } #[test] fn partial_one_of_test() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, u8> { one_of(['a', 'b']).parse_next(i) } let a = &b"abcd"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Ok( ( Partial { input: [ 98, 99, 100, ], partial: true, }, 97, ), ) "#]] .raw() ); let b = &b"cde"[..]; assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 99, 100, 101, ], partial: true, }, }, ), ) "#]] .raw() ); fn utf8<'i>(i: &mut Partial<&'i str>) -> TestResult, char> { one_of(['+', '\u{FF0B}']).parse_next(i) } assert!(utf8.parse_peek(Partial::new("+")).is_ok()); assert!(utf8.parse_peek(Partial::new("\u{FF0B}")).is_ok()); } #[test] fn char_byteslice() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, char> { 'c'.parse_next(i) } let a = &b"abcd"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 97, 98, 99, 100, ], partial: true, }, }, ), ) "#]] .raw() ); let b = &b"cde"[..]; assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Ok( ( Partial { input: [ 100, 101, ], partial: true, }, 'c', ), ) "#]] .raw() ); } #[test] fn char_str() { fn f<'i>(i: &mut Partial<&'i str>) -> TestResult, char> { 'c'.parse_next(i) } let a = "abcd"; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Backtrack( InputError { input: Partial { input: "abcd", partial: true, }, }, ), ) "#]] .raw() ); let b = "cde"; assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Ok( ( Partial { input: "de", partial: true, }, 'c', ), ) "#]] .raw() ); } #[test] fn partial_none_of_test() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, u8> { none_of(['a', 'b']).parse_next(i) } let a = &b"abcd"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 97, 98, 99, 100, ], partial: true, }, }, ), ) "#]] .raw() ); let b = &b"cde"[..]; assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Ok( ( Partial { input: [ 100, 101, ], partial: true, }, 99, ), ) "#]] .raw() ); } #[test] fn partial_is_a() { fn a_or_b<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_while(1.., ['a', 'b']).parse_next(i) } let a = Partial::new(&b"abcd"[..]); assert_parse!( a_or_b.parse_peek(a), str![[r#" Ok( ( Partial { input: [ 99, 100, ], partial: true, }, [ 97, 98, ], ), ) "#]] .raw() ); let b = Partial::new(&b"bcde"[..]); assert_parse!( a_or_b.parse_peek(b), str![[r#" Ok( ( Partial { input: [ 99, 100, 101, ], partial: true, }, [ 98, ], ), ) "#]] .raw() ); let c = Partial::new(&b"cdef"[..]); assert_parse!( a_or_b.parse_peek(c), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 99, 100, 101, 102, ], partial: true, }, }, ), ) "#]] .raw() ); let d = Partial::new(&b"bacdef"[..]); assert_parse!( a_or_b.parse_peek(d), str![[r#" Ok( ( Partial { input: [ 99, 100, 101, 102, ], partial: true, }, [ 98, 97, ], ), ) "#]] .raw() ); } #[test] fn partial_is_not() { fn a_or_b<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_till(1.., ['a', 'b']).parse_next(i) } let a = Partial::new(&b"cdab"[..]); assert_parse!( a_or_b.parse_peek(a), str![[r#" Ok( ( Partial { input: [ 97, 98, ], partial: true, }, [ 99, 100, ], ), ) "#]] .raw() ); let b = Partial::new(&b"cbde"[..]); assert_parse!( a_or_b.parse_peek(b), str![[r#" Ok( ( Partial { input: [ 98, 100, 101, ], partial: true, }, [ 99, ], ), ) "#]] .raw() ); let c = Partial::new(&b"abab"[..]); assert_parse!( a_or_b.parse_peek(c), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 97, 98, 97, 98, ], partial: true, }, }, ), ) "#]] .raw() ); let d = Partial::new(&b"cdefba"[..]); assert_parse!( a_or_b.parse_peek(d), str![[r#" Ok( ( Partial { input: [ 98, 97, ], partial: true, }, [ 99, 100, 101, 102, ], ), ) "#]] .raw() ); let e = Partial::new(&b"e"[..]); assert_parse!( a_or_b.parse_peek(e), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); } #[test] fn partial_take_until_incomplete() { fn y<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_until(0.., "end").parse_next(i) } assert_parse!( y.parse_peek(Partial::new(&b"nd"[..])), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( y.parse_peek(Partial::new(&b"123"[..])), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( y.parse_peek(Partial::new(&b"123en"[..])), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); } #[test] fn partial_take_until_incomplete_s() { fn ys<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_until(0.., "end").parse_next(i) } assert_parse!( ys.parse_peek(Partial::new("123en")), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); } #[test] fn partial_take() { use crate::ascii::{ alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit, multispace1 as multispace, oct_digit1 as oct_digit, space1 as space, }; fn x<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { delimited("").take().parse_next(i) } let r = x.parse_peek(Partial::new(&b" aaa"[..])); assert_parse!( r, str![[r#" Ok( ( Partial { input: [ 32, 97, 97, 97, ], partial: true, }, [ 60, 33, 45, 45, 32, 97, 98, 99, 32, 45, 45, 62, ], ), ) "#]] .raw() ); fn ya<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { alpha.take().parse_next(i) } let ra = ya.parse_peek(Partial::new(&b"abc;"[..])); assert_parse!( ra, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 97, 98, 99, ], ), ) "#]] .raw() ); fn yd<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { digit.take().parse_next(i) } let rd = yd.parse_peek(Partial::new(&b"123;"[..])); assert_parse!( rd, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 49, 50, 51, ], ), ) "#]] .raw() ); fn yhd<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { hex_digit.take().parse_next(i) } let rhd = yhd.parse_peek(Partial::new(&b"123abcDEF;"[..])); assert_parse!( rhd, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 49, 50, 51, 97, 98, 99, 68, 69, 70, ], ), ) "#]] .raw() ); fn yod<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { oct_digit.take().parse_next(i) } let rod = yod.parse_peek(Partial::new(&b"1234567;"[..])); assert_parse!( rod, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 49, 50, 51, 52, 53, 54, 55, ], ), ) "#]] .raw() ); fn yan<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { alphanumeric.take().parse_next(i) } let ran = yan.parse_peek(Partial::new(&b"123abc;"[..])); assert_parse!( ran, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 49, 50, 51, 97, 98, 99, ], ), ) "#]] .raw() ); fn ys<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { space.take().parse_next(i) } let rs = ys.parse_peek(Partial::new(&b" \t;"[..])); assert_parse!( rs, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 32, 9, ], ), ) "#]] .raw() ); fn yms<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { multispace.take().parse_next(i) } let rms = yms.parse_peek(Partial::new(&b" \t\r\n;"[..])); assert_parse!( rms, str![[r#" Ok( ( Partial { input: [ 59, ], partial: true, }, [ 32, 9, 13, 10, ], ), ) "#]] .raw() ); } #[test] fn partial_take_while0() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_while(0.., AsChar::is_alpha).parse_next(i) } let a = &b""[..]; let b = &b"abcd"[..]; let c = &b"abcd123"[..]; let d = &b"123"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(c)), str![[r#" Ok( ( Partial { input: [ 49, 50, 51, ], partial: true, }, [ 97, 98, 99, 100, ], ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(d)), str![[r#" Ok( ( Partial { input: [ 49, 50, 51, ], partial: true, }, [], ), ) "#]] .raw() ); } #[test] fn partial_take_while1() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_while(1.., AsChar::is_alpha).parse_next(i) } let a = &b""[..]; let b = &b"abcd"[..]; let c = &b"abcd123"[..]; let d = &b"123"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(c)), str![[r#" Ok( ( Partial { input: [ 49, 50, 51, ], partial: true, }, [ 97, 98, 99, 100, ], ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(d)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 49, 50, 51, ], partial: true, }, }, ), ) "#]] .raw() ); } #[test] fn partial_take_while_m_n() { fn x<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_while(2..=4, AsChar::is_alpha).parse_next(i) } let a = &b""[..]; let b = &b"a"[..]; let c = &b"abc"[..]; let d = &b"abc123"[..]; let e = &b"abcde"[..]; let f = &b"123"[..]; assert_parse!( x.parse_peek(Partial::new(a)), str![[r#" Err( Incomplete( Size( 2, ), ), ) "#]] .raw() ); assert_parse!( x.parse_peek(Partial::new(b)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( x.parse_peek(Partial::new(c)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( x.parse_peek(Partial::new(d)), str![[r#" Ok( ( Partial { input: [ 49, 50, 51, ], partial: true, }, [ 97, 98, 99, ], ), ) "#]] .raw() ); assert_parse!( x.parse_peek(Partial::new(e)), str![[r#" Ok( ( Partial { input: [ 101, ], partial: true, }, [ 97, 98, 99, 100, ], ), ) "#]] .raw() ); assert_parse!( x.parse_peek(Partial::new(f)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 49, 50, 51, ], partial: true, }, }, ), ) "#]] .raw() ); } #[test] fn partial_take_till0() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_till(0.., AsChar::is_alpha).parse_next(i) } let a = &b""[..]; let b = &b"abcd"[..]; let c = &b"123abcd"[..]; let d = &b"123"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Ok( ( Partial { input: [ 97, 98, 99, 100, ], partial: true, }, [], ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(c)), str![[r#" Ok( ( Partial { input: [ 97, 98, 99, 100, ], partial: true, }, [ 49, 50, 51, ], ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(d)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); } #[test] fn partial_take_till1() { fn f<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_till(1.., AsChar::is_alpha).parse_next(i) } let a = &b""[..]; let b = &b"abcd"[..]; let c = &b"123abcd"[..]; let d = &b"123"[..]; assert_parse!( f.parse_peek(Partial::new(a)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(b)), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 97, 98, 99, 100, ], partial: true, }, }, ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(c)), str![[r#" Ok( ( Partial { input: [ 97, 98, 99, 100, ], partial: true, }, [ 49, 50, 51, ], ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new(d)), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); } #[test] fn partial_take_while_utf8() { fn f<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(0.., |c| c != '點').parse_next(i) } assert_parse!( f.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd點")), str![[r#" Ok( ( Partial { input: "點", partial: true, }, "abcd", ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd點a")), str![[r#" Ok( ( Partial { input: "點a", partial: true, }, "abcd", ), ) "#]] .raw() ); fn g<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(0.., |c| c == '點').parse_next(i) } assert_parse!( g.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點abcd")), str![[r#" Ok( ( Partial { input: "abcd", partial: true, }, "點", ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點點點a")), str![[r#" Ok( ( Partial { input: "a", partial: true, }, "點點點", ), ) "#]] .raw() ); } #[test] fn partial_take_till0_utf8() { fn f<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_till(0.., |c| c == '點').parse_next(i) } assert_parse!( f.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd點")), str![[r#" Ok( ( Partial { input: "點", partial: true, }, "abcd", ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("abcd點a")), str![[r#" Ok( ( Partial { input: "點a", partial: true, }, "abcd", ), ) "#]] .raw() ); fn g<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_till(0.., |c| c != '點').parse_next(i) } assert_parse!( g.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點abcd")), str![[r#" Ok( ( Partial { input: "abcd", partial: true, }, "點", ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點點點a")), str![[r#" Ok( ( Partial { input: "a", partial: true, }, "點點點", ), ) "#]] .raw() ); } #[test] fn partial_take_utf8() { fn f<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take(3_usize).parse_next(i) } assert_parse!( f.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("ab")), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("點")), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("ab點cd")), str![[r#" Ok( ( Partial { input: "cd", partial: true, }, "ab點", ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("a點bcd")), str![[r#" Ok( ( Partial { input: "cd", partial: true, }, "a點b", ), ) "#]] .raw() ); assert_parse!( f.parse_peek(Partial::new("a點b")), str![[r#" Ok( ( Partial { input: "", partial: true, }, "a點b", ), ) "#]] .raw() ); fn g<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(0.., |c| c == '點').parse_next(i) } assert_parse!( g.parse_peek(Partial::new("")), str![[r#" Err( Incomplete( Size( 1, ), ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點abcd")), str![[r#" Ok( ( Partial { input: "abcd", partial: true, }, "點", ), ) "#]] .raw() ); assert_parse!( g.parse_peek(Partial::new("點點點a")), str![[r#" Ok( ( Partial { input: "a", partial: true, }, "點點點", ), ) "#]] .raw() ); } #[test] fn partial_take_while_m_n_utf8_fixed() { fn parser<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(1, |c| c == 'A' || c == '😃').parse_next(i) } assert_parse!( parser.parse_peek(Partial::new("A!")), str![[r#" Ok( ( Partial { input: "!", partial: true, }, "A", ), ) "#]] .raw() ); assert_parse!( parser.parse_peek(Partial::new("😃!")), str![[r#" Ok( ( Partial { input: "!", partial: true, }, "😃", ), ) "#]] .raw() ); } #[test] fn partial_take_while_m_n_utf8_range() { fn parser<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(1..=2, |c| c == 'A' || c == '😃').parse_next(i) } assert_parse!( parser.parse_peek(Partial::new("A!")), str![[r#" Ok( ( Partial { input: "!", partial: true, }, "A", ), ) "#]] .raw() ); assert_parse!( parser.parse_peek(Partial::new("😃!")), str![[r#" Ok( ( Partial { input: "!", partial: true, }, "😃", ), ) "#]] .raw() ); } #[test] fn partial_take_while_m_n_utf8_full_match_fixed() { fn parser<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(1, |c: char| c.is_alphabetic()).parse_next(i) } assert_parse!( parser.parse_peek(Partial::new("øn")), str![[r#" Ok( ( Partial { input: "n", partial: true, }, "ø", ), ) "#]] .raw() ); } #[test] fn partial_take_while_m_n_utf8_full_match_range() { fn parser<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { take_while(1..=2, |c: char| c.is_alphabetic()).parse_next(i) } assert_parse!( parser.parse_peek(Partial::new("øn")), str![[r#" Ok( ( Partial { input: "", partial: true, }, "øn", ), ) "#]] .raw() ); } #[test] #[cfg(feature = "std")] fn partial_take_take_while0() { fn x<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { take_while(0.., AsChar::is_alphanum).parse_next(i) } fn y<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { x.take().parse_next(i) } assert_parse!( x.parse_peek(Partial::new(&b"ab."[..])), str![[r#" Ok( ( Partial { input: [ 46, ], partial: true, }, [ 97, 98, ], ), ) "#]] .raw() ); assert_parse!( y.parse_peek(Partial::new(&b"ab."[..])), str![[r#" Ok( ( Partial { input: [ 46, ], partial: true, }, [ 97, 98, ], ), ) "#]] .raw() ); } #[test] fn partial_literal_case_insensitive() { fn caseless_bytes<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { literal(Caseless("ABcd")).parse_next(i) } assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"aBCdefgh"[..])), str![[r#" Ok( ( Partial { input: [ 101, 102, 103, 104, ], partial: true, }, [ 97, 66, 67, 100, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"abcdefgh"[..])), str![[r#" Ok( ( Partial { input: [ 101, 102, 103, 104, ], partial: true, }, [ 97, 98, 99, 100, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"ABCDefgh"[..])), str![[r#" Ok( ( Partial { input: [ 101, 102, 103, 104, ], partial: true, }, [ 65, 66, 67, 68, ], ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"ab"[..])), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"Hello"[..])), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 72, 101, 108, 108, 111, ], partial: true, }, }, ), ) "#]] .raw() ); assert_parse!( caseless_bytes.parse_peek(Partial::new(&b"Hel"[..])), str![[r#" Err( Backtrack( InputError { input: Partial { input: [ 72, 101, 108, ], partial: true, }, }, ), ) "#]] .raw() ); fn caseless_str<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { literal(Caseless("ABcd")).parse_next(i) } assert_parse!( caseless_str.parse_peek(Partial::new("aBCdefgh")), str![[r#" Ok( ( Partial { input: "efgh", partial: true, }, "aBCd", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek(Partial::new("abcdefgh")), str![[r#" Ok( ( Partial { input: "efgh", partial: true, }, "abcd", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek(Partial::new("ABCDefgh")), str![[r#" Ok( ( Partial { input: "efgh", partial: true, }, "ABCD", ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek(Partial::new("ab")), str![[r#" Err( Incomplete( Unknown, ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek(Partial::new("Hello")), str![[r#" Err( Backtrack( InputError { input: Partial { input: "Hello", partial: true, }, }, ), ) "#]] .raw() ); assert_parse!( caseless_str.parse_peek(Partial::new("Hel")), str![[r#" Err( Backtrack( InputError { input: Partial { input: "Hel", partial: true, }, }, ), ) "#]] .raw() ); fn matches_kelvin<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { literal(Caseless("k")).parse_next(i) } assert_parse!( matches_kelvin.parse_peek(Partial::new("K")), str![[r#" Err( Backtrack( InputError { input: Partial { input: "K", partial: true, }, }, ), ) "#]] .raw() ); fn is_kelvin<'i>(i: &mut Partial<&'i str>) -> TestResult, &'i str> { literal(Caseless("K")).parse_next(i) } assert_parse!( is_kelvin.parse_peek(Partial::new("k")), str![[r#" Err( Backtrack( InputError { input: Partial { input: "k", partial: true, }, }, ), ) "#]] .raw() ); } #[test] fn partial_literal_fixed_size_array() { fn test<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { literal([0x42]).parse_next(i) } fn test2<'i>(i: &mut Partial<&'i [u8]>) -> TestResult, &'i [u8]> { literal(&[0x42]).parse_next(i) } let input = Partial::new(&[0x42, 0x00][..]); assert_parse!( test.parse_peek(input), str![[r#" Ok( ( Partial { input: [ 0, ], partial: true, }, [ 66, ], ), ) "#]] .raw() ); assert_parse!( test2.parse_peek(input), str![[r#" Ok( ( Partial { input: [ 0, ], partial: true, }, [ 66, ], ), ) "#]] .raw() ); } #[test] fn rest_on_slices() { let input: &[u8] = &b"Hello, world!"[..]; assert_parse!( rest.parse_peek(input), str![[r#" Ok( ( [], [ 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, ], ), ) "#]] .raw() ); } #[test] fn rest_on_strs() { let input: &str = "Hello, world!"; assert_parse!( rest.parse_peek(input), str![[r#" Ok( ( "", "Hello, world!", ), ) "#]] .raw() ); } #[test] fn rest_len_on_slices() { let input: &[u8] = &b"Hello, world!"[..]; assert_parse!( rest_len.parse_peek(input), str![[r#" Ok( ( [ 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, ], 13, ), ) "#]] .raw() ); } #[test] fn tokenslice_literals() { type TokenSlice<'i, 't> = crate::stream::TokenSlice<'i, Token<'t>>; #[derive(Clone, Debug, PartialEq, Eq)] struct Token<'i> { kind: TokenKind, raw: &'i str, } impl PartialEq<&str> for Token<'_> { fn eq(&self, other: &&str) -> bool { self.raw == *other } } impl PartialEq for Token<'_> { fn eq(&self, other: &TokenKind) -> bool { self.kind == *other } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum TokenKind { If, LeftParen, RightParen, LeftCurly, RightCurly, Value, } impl<'i, 't> Parser, &'i Token<'t>, ErrMode>>> for TokenKind { fn parse_next( &mut self, input: &mut TokenSlice<'i, 't>, ) -> TestResult, &'i Token<'t>> { literal(*self).parse_next(input).map(|t| &t[0]) } } let input = [ Token { kind: TokenKind::If, raw: "if", }, Token { kind: TokenKind::LeftParen, raw: "(", }, Token { kind: TokenKind::Value, raw: "hello", }, Token { kind: TokenKind::RightParen, raw: ")", }, Token { kind: TokenKind::LeftCurly, raw: "{", }, Token { kind: TokenKind::RightCurly, raw: "}", }, ]; let mut input = TokenSlice::new(&input); assert_parse!( ( TokenKind::If, TokenKind::LeftParen, "hello", TokenKind::RightParen ) .parse_next(&mut input), str![[r#" Ok( ( Token { kind: If, raw: "if", }, Token { kind: LeftParen, raw: "(", }, [ Token { kind: Value, raw: "hello", }, ], Token { kind: RightParen, raw: ")", }, ), ) "#]] .raw() ); }