16855e09eSopenharmony_ci//! Parsers recognizing bytes streams, complete input version 26855e09eSopenharmony_ci 36855e09eSopenharmony_ciuse crate::error::ErrorKind; 46855e09eSopenharmony_ciuse crate::error::ParseError; 56855e09eSopenharmony_ciuse crate::internal::{Err, IResult, Parser}; 66855e09eSopenharmony_ciuse crate::lib::std::ops::RangeFrom; 76855e09eSopenharmony_ciuse crate::lib::std::result::Result::*; 86855e09eSopenharmony_ciuse crate::traits::{ 96855e09eSopenharmony_ci Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, 106855e09eSopenharmony_ci InputTakeAtPosition, Slice, ToUsize, 116855e09eSopenharmony_ci}; 126855e09eSopenharmony_ci 136855e09eSopenharmony_ci/// Recognizes a pattern 146855e09eSopenharmony_ci/// 156855e09eSopenharmony_ci/// The input data will be compared to the tag combinator's argument and will return the part of 166855e09eSopenharmony_ci/// the input that matches the argument 176855e09eSopenharmony_ci/// 186855e09eSopenharmony_ci/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern 196855e09eSopenharmony_ci/// # Example 206855e09eSopenharmony_ci/// ```rust 216855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 226855e09eSopenharmony_ci/// use nom::bytes::complete::tag; 236855e09eSopenharmony_ci/// 246855e09eSopenharmony_ci/// fn parser(s: &str) -> IResult<&str, &str> { 256855e09eSopenharmony_ci/// tag("Hello")(s) 266855e09eSopenharmony_ci/// } 276855e09eSopenharmony_ci/// 286855e09eSopenharmony_ci/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); 296855e09eSopenharmony_ci/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); 306855e09eSopenharmony_ci/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); 316855e09eSopenharmony_ci/// ``` 326855e09eSopenharmony_cipub fn tag<T, Input, Error: ParseError<Input>>( 336855e09eSopenharmony_ci tag: T, 346855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 356855e09eSopenharmony_ciwhere 366855e09eSopenharmony_ci Input: InputTake + Compare<T>, 376855e09eSopenharmony_ci T: InputLength + Clone, 386855e09eSopenharmony_ci{ 396855e09eSopenharmony_ci move |i: Input| { 406855e09eSopenharmony_ci let tag_len = tag.input_len(); 416855e09eSopenharmony_ci let t = tag.clone(); 426855e09eSopenharmony_ci let res: IResult<_, _, Error> = match i.compare(t) { 436855e09eSopenharmony_ci CompareResult::Ok => Ok(i.take_split(tag_len)), 446855e09eSopenharmony_ci _ => { 456855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::Tag; 466855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind(i, e))) 476855e09eSopenharmony_ci } 486855e09eSopenharmony_ci }; 496855e09eSopenharmony_ci res 506855e09eSopenharmony_ci } 516855e09eSopenharmony_ci} 526855e09eSopenharmony_ci 536855e09eSopenharmony_ci/// Recognizes a case insensitive pattern. 546855e09eSopenharmony_ci/// 556855e09eSopenharmony_ci/// The input data will be compared to the tag combinator's argument and will return the part of 566855e09eSopenharmony_ci/// the input that matches the argument with no regard to case. 576855e09eSopenharmony_ci/// 586855e09eSopenharmony_ci/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern. 596855e09eSopenharmony_ci/// # Example 606855e09eSopenharmony_ci/// ```rust 616855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 626855e09eSopenharmony_ci/// use nom::bytes::complete::tag_no_case; 636855e09eSopenharmony_ci/// 646855e09eSopenharmony_ci/// fn parser(s: &str) -> IResult<&str, &str> { 656855e09eSopenharmony_ci/// tag_no_case("hello")(s) 666855e09eSopenharmony_ci/// } 676855e09eSopenharmony_ci/// 686855e09eSopenharmony_ci/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); 696855e09eSopenharmony_ci/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); 706855e09eSopenharmony_ci/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); 716855e09eSopenharmony_ci/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); 726855e09eSopenharmony_ci/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); 736855e09eSopenharmony_ci/// ``` 746855e09eSopenharmony_cipub fn tag_no_case<T, Input, Error: ParseError<Input>>( 756855e09eSopenharmony_ci tag: T, 766855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 776855e09eSopenharmony_ciwhere 786855e09eSopenharmony_ci Input: InputTake + Compare<T>, 796855e09eSopenharmony_ci T: InputLength + Clone, 806855e09eSopenharmony_ci{ 816855e09eSopenharmony_ci move |i: Input| { 826855e09eSopenharmony_ci let tag_len = tag.input_len(); 836855e09eSopenharmony_ci let t = tag.clone(); 846855e09eSopenharmony_ci 856855e09eSopenharmony_ci let res: IResult<_, _, Error> = match (i).compare_no_case(t) { 866855e09eSopenharmony_ci CompareResult::Ok => Ok(i.take_split(tag_len)), 876855e09eSopenharmony_ci _ => { 886855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::Tag; 896855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind(i, e))) 906855e09eSopenharmony_ci } 916855e09eSopenharmony_ci }; 926855e09eSopenharmony_ci res 936855e09eSopenharmony_ci } 946855e09eSopenharmony_ci} 956855e09eSopenharmony_ci 966855e09eSopenharmony_ci/// Parse till certain characters are met. 976855e09eSopenharmony_ci/// 986855e09eSopenharmony_ci/// The parser will return the longest slice till one of the characters of the combinator's argument are met. 996855e09eSopenharmony_ci/// 1006855e09eSopenharmony_ci/// It doesn't consume the matched character. 1016855e09eSopenharmony_ci/// 1026855e09eSopenharmony_ci/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met. 1036855e09eSopenharmony_ci/// # Example 1046855e09eSopenharmony_ci/// ```rust 1056855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 1066855e09eSopenharmony_ci/// use nom::bytes::complete::is_not; 1076855e09eSopenharmony_ci/// 1086855e09eSopenharmony_ci/// fn not_space(s: &str) -> IResult<&str, &str> { 1096855e09eSopenharmony_ci/// is_not(" \t\r\n")(s) 1106855e09eSopenharmony_ci/// } 1116855e09eSopenharmony_ci/// 1126855e09eSopenharmony_ci/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); 1136855e09eSopenharmony_ci/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); 1146855e09eSopenharmony_ci/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace"))); 1156855e09eSopenharmony_ci/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot)))); 1166855e09eSopenharmony_ci/// ``` 1176855e09eSopenharmony_cipub fn is_not<T, Input, Error: ParseError<Input>>( 1186855e09eSopenharmony_ci arr: T, 1196855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 1206855e09eSopenharmony_ciwhere 1216855e09eSopenharmony_ci Input: InputTakeAtPosition, 1226855e09eSopenharmony_ci T: FindToken<<Input as InputTakeAtPosition>::Item>, 1236855e09eSopenharmony_ci{ 1246855e09eSopenharmony_ci move |i: Input| { 1256855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::IsNot; 1266855e09eSopenharmony_ci i.split_at_position1_complete(|c| arr.find_token(c), e) 1276855e09eSopenharmony_ci } 1286855e09eSopenharmony_ci} 1296855e09eSopenharmony_ci 1306855e09eSopenharmony_ci/// Returns the longest slice of the matches the pattern. 1316855e09eSopenharmony_ci/// 1326855e09eSopenharmony_ci/// The parser will return the longest slice consisting of the characters in provided in the 1336855e09eSopenharmony_ci/// combinator's argument. 1346855e09eSopenharmony_ci/// 1356855e09eSopenharmony_ci/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met. 1366855e09eSopenharmony_ci/// # Example 1376855e09eSopenharmony_ci/// ```rust 1386855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 1396855e09eSopenharmony_ci/// use nom::bytes::complete::is_a; 1406855e09eSopenharmony_ci/// 1416855e09eSopenharmony_ci/// fn hex(s: &str) -> IResult<&str, &str> { 1426855e09eSopenharmony_ci/// is_a("1234567890ABCDEF")(s) 1436855e09eSopenharmony_ci/// } 1446855e09eSopenharmony_ci/// 1456855e09eSopenharmony_ci/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); 1466855e09eSopenharmony_ci/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); 1476855e09eSopenharmony_ci/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); 1486855e09eSopenharmony_ci/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E"))); 1496855e09eSopenharmony_ci/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA)))); 1506855e09eSopenharmony_ci/// ``` 1516855e09eSopenharmony_cipub fn is_a<T, Input, Error: ParseError<Input>>( 1526855e09eSopenharmony_ci arr: T, 1536855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 1546855e09eSopenharmony_ciwhere 1556855e09eSopenharmony_ci Input: InputTakeAtPosition, 1566855e09eSopenharmony_ci T: FindToken<<Input as InputTakeAtPosition>::Item>, 1576855e09eSopenharmony_ci{ 1586855e09eSopenharmony_ci move |i: Input| { 1596855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::IsA; 1606855e09eSopenharmony_ci i.split_at_position1_complete(|c| !arr.find_token(c), e) 1616855e09eSopenharmony_ci } 1626855e09eSopenharmony_ci} 1636855e09eSopenharmony_ci 1646855e09eSopenharmony_ci/// Returns the longest input slice (if any) that matches the predicate. 1656855e09eSopenharmony_ci/// 1666855e09eSopenharmony_ci/// The parser will return the longest slice that matches the given predicate *(a function that 1676855e09eSopenharmony_ci/// takes the input and returns a bool)*. 1686855e09eSopenharmony_ci/// # Example 1696855e09eSopenharmony_ci/// ```rust 1706855e09eSopenharmony_ci/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 1716855e09eSopenharmony_ci/// use nom::bytes::complete::take_while; 1726855e09eSopenharmony_ci/// use nom::character::is_alphabetic; 1736855e09eSopenharmony_ci/// 1746855e09eSopenharmony_ci/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 1756855e09eSopenharmony_ci/// take_while(is_alphabetic)(s) 1766855e09eSopenharmony_ci/// } 1776855e09eSopenharmony_ci/// 1786855e09eSopenharmony_ci/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 1796855e09eSopenharmony_ci/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); 1806855e09eSopenharmony_ci/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 1816855e09eSopenharmony_ci/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..]))); 1826855e09eSopenharmony_ci/// ``` 1836855e09eSopenharmony_cipub fn take_while<F, Input, Error: ParseError<Input>>( 1846855e09eSopenharmony_ci cond: F, 1856855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 1866855e09eSopenharmony_ciwhere 1876855e09eSopenharmony_ci Input: InputTakeAtPosition, 1886855e09eSopenharmony_ci F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 1896855e09eSopenharmony_ci{ 1906855e09eSopenharmony_ci move |i: Input| i.split_at_position_complete(|c| !cond(c)) 1916855e09eSopenharmony_ci} 1926855e09eSopenharmony_ci 1936855e09eSopenharmony_ci/// Returns the longest (at least 1) input slice that matches the predicate. 1946855e09eSopenharmony_ci/// 1956855e09eSopenharmony_ci/// The parser will return the longest slice that matches the given predicate *(a function that 1966855e09eSopenharmony_ci/// takes the input and returns a bool)*. 1976855e09eSopenharmony_ci/// 1986855e09eSopenharmony_ci/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. 1996855e09eSopenharmony_ci/// # Example 2006855e09eSopenharmony_ci/// ```rust 2016855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 2026855e09eSopenharmony_ci/// use nom::bytes::complete::take_while1; 2036855e09eSopenharmony_ci/// use nom::character::is_alphabetic; 2046855e09eSopenharmony_ci/// 2056855e09eSopenharmony_ci/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 2066855e09eSopenharmony_ci/// take_while1(is_alphabetic)(s) 2076855e09eSopenharmony_ci/// } 2086855e09eSopenharmony_ci/// 2096855e09eSopenharmony_ci/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 2106855e09eSopenharmony_ci/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 2116855e09eSopenharmony_ci/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); 2126855e09eSopenharmony_ci/// ``` 2136855e09eSopenharmony_cipub fn take_while1<F, Input, Error: ParseError<Input>>( 2146855e09eSopenharmony_ci cond: F, 2156855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 2166855e09eSopenharmony_ciwhere 2176855e09eSopenharmony_ci Input: InputTakeAtPosition, 2186855e09eSopenharmony_ci F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 2196855e09eSopenharmony_ci{ 2206855e09eSopenharmony_ci move |i: Input| { 2216855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::TakeWhile1; 2226855e09eSopenharmony_ci i.split_at_position1_complete(|c| !cond(c), e) 2236855e09eSopenharmony_ci } 2246855e09eSopenharmony_ci} 2256855e09eSopenharmony_ci 2266855e09eSopenharmony_ci/// Returns the longest (m <= len <= n) input slice that matches the predicate. 2276855e09eSopenharmony_ci/// 2286855e09eSopenharmony_ci/// The parser will return the longest slice that matches the given predicate *(a function that 2296855e09eSopenharmony_ci/// takes the input and returns a bool)*. 2306855e09eSopenharmony_ci/// 2316855e09eSopenharmony_ci/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out 2326855e09eSopenharmony_ci/// of range (m <= len <= n). 2336855e09eSopenharmony_ci/// # Example 2346855e09eSopenharmony_ci/// ```rust 2356855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 2366855e09eSopenharmony_ci/// use nom::bytes::complete::take_while_m_n; 2376855e09eSopenharmony_ci/// use nom::character::is_alphabetic; 2386855e09eSopenharmony_ci/// 2396855e09eSopenharmony_ci/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 2406855e09eSopenharmony_ci/// take_while_m_n(3, 6, is_alphabetic)(s) 2416855e09eSopenharmony_ci/// } 2426855e09eSopenharmony_ci/// 2436855e09eSopenharmony_ci/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 2446855e09eSopenharmony_ci/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); 2456855e09eSopenharmony_ci/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 2466855e09eSopenharmony_ci/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN)))); 2476855e09eSopenharmony_ci/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); 2486855e09eSopenharmony_ci/// ``` 2496855e09eSopenharmony_cipub fn take_while_m_n<F, Input, Error: ParseError<Input>>( 2506855e09eSopenharmony_ci m: usize, 2516855e09eSopenharmony_ci n: usize, 2526855e09eSopenharmony_ci cond: F, 2536855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 2546855e09eSopenharmony_ciwhere 2556855e09eSopenharmony_ci Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>, 2566855e09eSopenharmony_ci F: Fn(<Input as InputIter>::Item) -> bool, 2576855e09eSopenharmony_ci{ 2586855e09eSopenharmony_ci move |i: Input| { 2596855e09eSopenharmony_ci let input = i; 2606855e09eSopenharmony_ci 2616855e09eSopenharmony_ci match input.position(|c| !cond(c)) { 2626855e09eSopenharmony_ci Some(idx) => { 2636855e09eSopenharmony_ci if idx >= m { 2646855e09eSopenharmony_ci if idx <= n { 2656855e09eSopenharmony_ci let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { 2666855e09eSopenharmony_ci Ok(input.take_split(index)) 2676855e09eSopenharmony_ci } else { 2686855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind( 2696855e09eSopenharmony_ci input, 2706855e09eSopenharmony_ci ErrorKind::TakeWhileMN, 2716855e09eSopenharmony_ci ))) 2726855e09eSopenharmony_ci }; 2736855e09eSopenharmony_ci res 2746855e09eSopenharmony_ci } else { 2756855e09eSopenharmony_ci let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { 2766855e09eSopenharmony_ci Ok(input.take_split(index)) 2776855e09eSopenharmony_ci } else { 2786855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind( 2796855e09eSopenharmony_ci input, 2806855e09eSopenharmony_ci ErrorKind::TakeWhileMN, 2816855e09eSopenharmony_ci ))) 2826855e09eSopenharmony_ci }; 2836855e09eSopenharmony_ci res 2846855e09eSopenharmony_ci } 2856855e09eSopenharmony_ci } else { 2866855e09eSopenharmony_ci let e = ErrorKind::TakeWhileMN; 2876855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind(input, e))) 2886855e09eSopenharmony_ci } 2896855e09eSopenharmony_ci } 2906855e09eSopenharmony_ci None => { 2916855e09eSopenharmony_ci let len = input.input_len(); 2926855e09eSopenharmony_ci if len >= n { 2936855e09eSopenharmony_ci match input.slice_index(n) { 2946855e09eSopenharmony_ci Ok(index) => Ok(input.take_split(index)), 2956855e09eSopenharmony_ci Err(_needed) => Err(Err::Error(Error::from_error_kind( 2966855e09eSopenharmony_ci input, 2976855e09eSopenharmony_ci ErrorKind::TakeWhileMN, 2986855e09eSopenharmony_ci ))), 2996855e09eSopenharmony_ci } 3006855e09eSopenharmony_ci } else if len >= m && len <= n { 3016855e09eSopenharmony_ci let res: IResult<_, _, Error> = Ok((input.slice(len..), input)); 3026855e09eSopenharmony_ci res 3036855e09eSopenharmony_ci } else { 3046855e09eSopenharmony_ci let e = ErrorKind::TakeWhileMN; 3056855e09eSopenharmony_ci Err(Err::Error(Error::from_error_kind(input, e))) 3066855e09eSopenharmony_ci } 3076855e09eSopenharmony_ci } 3086855e09eSopenharmony_ci } 3096855e09eSopenharmony_ci } 3106855e09eSopenharmony_ci} 3116855e09eSopenharmony_ci 3126855e09eSopenharmony_ci/// Returns the longest input slice (if any) till a predicate is met. 3136855e09eSopenharmony_ci/// 3146855e09eSopenharmony_ci/// The parser will return the longest slice till the given predicate *(a function that 3156855e09eSopenharmony_ci/// takes the input and returns a bool)*. 3166855e09eSopenharmony_ci/// # Example 3176855e09eSopenharmony_ci/// ```rust 3186855e09eSopenharmony_ci/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 3196855e09eSopenharmony_ci/// use nom::bytes::complete::take_till; 3206855e09eSopenharmony_ci/// 3216855e09eSopenharmony_ci/// fn till_colon(s: &str) -> IResult<&str, &str> { 3226855e09eSopenharmony_ci/// take_till(|c| c == ':')(s) 3236855e09eSopenharmony_ci/// } 3246855e09eSopenharmony_ci/// 3256855e09eSopenharmony_ci/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); 3266855e09eSopenharmony_ci/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed 3276855e09eSopenharmony_ci/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); 3286855e09eSopenharmony_ci/// assert_eq!(till_colon(""), Ok(("", ""))); 3296855e09eSopenharmony_ci/// ``` 3306855e09eSopenharmony_cipub fn take_till<F, Input, Error: ParseError<Input>>( 3316855e09eSopenharmony_ci cond: F, 3326855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 3336855e09eSopenharmony_ciwhere 3346855e09eSopenharmony_ci Input: InputTakeAtPosition, 3356855e09eSopenharmony_ci F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 3366855e09eSopenharmony_ci{ 3376855e09eSopenharmony_ci move |i: Input| i.split_at_position_complete(|c| cond(c)) 3386855e09eSopenharmony_ci} 3396855e09eSopenharmony_ci 3406855e09eSopenharmony_ci/// Returns the longest (at least 1) input slice till a predicate is met. 3416855e09eSopenharmony_ci/// 3426855e09eSopenharmony_ci/// The parser will return the longest slice till the given predicate *(a function that 3436855e09eSopenharmony_ci/// takes the input and returns a bool)*. 3446855e09eSopenharmony_ci/// 3456855e09eSopenharmony_ci/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the 3466855e09eSopenharmony_ci/// predicate matches the first input. 3476855e09eSopenharmony_ci/// # Example 3486855e09eSopenharmony_ci/// ```rust 3496855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 3506855e09eSopenharmony_ci/// use nom::bytes::complete::take_till1; 3516855e09eSopenharmony_ci/// 3526855e09eSopenharmony_ci/// fn till_colon(s: &str) -> IResult<&str, &str> { 3536855e09eSopenharmony_ci/// take_till1(|c| c == ':')(s) 3546855e09eSopenharmony_ci/// } 3556855e09eSopenharmony_ci/// 3566855e09eSopenharmony_ci/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); 3576855e09eSopenharmony_ci/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); 3586855e09eSopenharmony_ci/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); 3596855e09eSopenharmony_ci/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1)))); 3606855e09eSopenharmony_ci/// ``` 3616855e09eSopenharmony_cipub fn take_till1<F, Input, Error: ParseError<Input>>( 3626855e09eSopenharmony_ci cond: F, 3636855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 3646855e09eSopenharmony_ciwhere 3656855e09eSopenharmony_ci Input: InputTakeAtPosition, 3666855e09eSopenharmony_ci F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 3676855e09eSopenharmony_ci{ 3686855e09eSopenharmony_ci move |i: Input| { 3696855e09eSopenharmony_ci let e: ErrorKind = ErrorKind::TakeTill1; 3706855e09eSopenharmony_ci i.split_at_position1_complete(|c| cond(c), e) 3716855e09eSopenharmony_ci } 3726855e09eSopenharmony_ci} 3736855e09eSopenharmony_ci 3746855e09eSopenharmony_ci/// Returns an input slice containing the first N input elements (Input[..N]). 3756855e09eSopenharmony_ci/// 3766855e09eSopenharmony_ci/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument. 3776855e09eSopenharmony_ci/// # Example 3786855e09eSopenharmony_ci/// ```rust 3796855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 3806855e09eSopenharmony_ci/// use nom::bytes::complete::take; 3816855e09eSopenharmony_ci/// 3826855e09eSopenharmony_ci/// fn take6(s: &str) -> IResult<&str, &str> { 3836855e09eSopenharmony_ci/// take(6usize)(s) 3846855e09eSopenharmony_ci/// } 3856855e09eSopenharmony_ci/// 3866855e09eSopenharmony_ci/// assert_eq!(take6("1234567"), Ok(("7", "123456"))); 3876855e09eSopenharmony_ci/// assert_eq!(take6("things"), Ok(("", "things"))); 3886855e09eSopenharmony_ci/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof)))); 3896855e09eSopenharmony_ci/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); 3906855e09eSopenharmony_ci/// ``` 3916855e09eSopenharmony_ci/// 3926855e09eSopenharmony_ci/// The units that are taken will depend on the input type. For example, for a 3936855e09eSopenharmony_ci/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will 3946855e09eSopenharmony_ci/// take that many `u8`'s: 3956855e09eSopenharmony_ci/// 3966855e09eSopenharmony_ci/// ```rust 3976855e09eSopenharmony_ci/// use nom::error::Error; 3986855e09eSopenharmony_ci/// use nom::bytes::complete::take; 3996855e09eSopenharmony_ci/// 4006855e09eSopenharmony_ci/// assert_eq!(take::<_, _, Error<_>>(1usize)(""), Ok(("", ""))); 4016855e09eSopenharmony_ci/// assert_eq!(take::<_, _, Error<_>>(1usize)("".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref()))); 4026855e09eSopenharmony_ci/// ``` 4036855e09eSopenharmony_cipub fn take<C, Input, Error: ParseError<Input>>( 4046855e09eSopenharmony_ci count: C, 4056855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 4066855e09eSopenharmony_ciwhere 4076855e09eSopenharmony_ci Input: InputIter + InputTake, 4086855e09eSopenharmony_ci C: ToUsize, 4096855e09eSopenharmony_ci{ 4106855e09eSopenharmony_ci let c = count.to_usize(); 4116855e09eSopenharmony_ci move |i: Input| match i.slice_index(c) { 4126855e09eSopenharmony_ci Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))), 4136855e09eSopenharmony_ci Ok(index) => Ok(i.take_split(index)), 4146855e09eSopenharmony_ci } 4156855e09eSopenharmony_ci} 4166855e09eSopenharmony_ci 4176855e09eSopenharmony_ci/// Returns the input slice up to the first occurrence of the pattern. 4186855e09eSopenharmony_ci/// 4196855e09eSopenharmony_ci/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` 4206855e09eSopenharmony_ci/// if the pattern wasn't met. 4216855e09eSopenharmony_ci/// # Example 4226855e09eSopenharmony_ci/// ```rust 4236855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 4246855e09eSopenharmony_ci/// use nom::bytes::complete::take_until; 4256855e09eSopenharmony_ci/// 4266855e09eSopenharmony_ci/// fn until_eof(s: &str) -> IResult<&str, &str> { 4276855e09eSopenharmony_ci/// take_until("eof")(s) 4286855e09eSopenharmony_ci/// } 4296855e09eSopenharmony_ci/// 4306855e09eSopenharmony_ci/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); 4316855e09eSopenharmony_ci/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); 4326855e09eSopenharmony_ci/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); 4336855e09eSopenharmony_ci/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); 4346855e09eSopenharmony_ci/// ``` 4356855e09eSopenharmony_cipub fn take_until<T, Input, Error: ParseError<Input>>( 4366855e09eSopenharmony_ci tag: T, 4376855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 4386855e09eSopenharmony_ciwhere 4396855e09eSopenharmony_ci Input: InputTake + FindSubstring<T>, 4406855e09eSopenharmony_ci T: InputLength + Clone, 4416855e09eSopenharmony_ci{ 4426855e09eSopenharmony_ci move |i: Input| { 4436855e09eSopenharmony_ci let t = tag.clone(); 4446855e09eSopenharmony_ci let res: IResult<_, _, Error> = match i.find_substring(t) { 4456855e09eSopenharmony_ci None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 4466855e09eSopenharmony_ci Some(index) => Ok(i.take_split(index)), 4476855e09eSopenharmony_ci }; 4486855e09eSopenharmony_ci res 4496855e09eSopenharmony_ci } 4506855e09eSopenharmony_ci} 4516855e09eSopenharmony_ci 4526855e09eSopenharmony_ci/// Returns the non empty input slice up to the first occurrence of the pattern. 4536855e09eSopenharmony_ci/// 4546855e09eSopenharmony_ci/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` 4556855e09eSopenharmony_ci/// if the pattern wasn't met. 4566855e09eSopenharmony_ci/// # Example 4576855e09eSopenharmony_ci/// ```rust 4586855e09eSopenharmony_ci/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 4596855e09eSopenharmony_ci/// use nom::bytes::complete::take_until1; 4606855e09eSopenharmony_ci/// 4616855e09eSopenharmony_ci/// fn until_eof(s: &str) -> IResult<&str, &str> { 4626855e09eSopenharmony_ci/// take_until1("eof")(s) 4636855e09eSopenharmony_ci/// } 4646855e09eSopenharmony_ci/// 4656855e09eSopenharmony_ci/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); 4666855e09eSopenharmony_ci/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); 4676855e09eSopenharmony_ci/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); 4686855e09eSopenharmony_ci/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); 4696855e09eSopenharmony_ci/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); 4706855e09eSopenharmony_ci/// ``` 4716855e09eSopenharmony_cipub fn take_until1<T, Input, Error: ParseError<Input>>( 4726855e09eSopenharmony_ci tag: T, 4736855e09eSopenharmony_ci) -> impl Fn(Input) -> IResult<Input, Input, Error> 4746855e09eSopenharmony_ciwhere 4756855e09eSopenharmony_ci Input: InputTake + FindSubstring<T>, 4766855e09eSopenharmony_ci T: InputLength + Clone, 4776855e09eSopenharmony_ci{ 4786855e09eSopenharmony_ci move |i: Input| { 4796855e09eSopenharmony_ci let t = tag.clone(); 4806855e09eSopenharmony_ci let res: IResult<_, _, Error> = match i.find_substring(t) { 4816855e09eSopenharmony_ci None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 4826855e09eSopenharmony_ci Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 4836855e09eSopenharmony_ci Some(index) => Ok(i.take_split(index)), 4846855e09eSopenharmony_ci }; 4856855e09eSopenharmony_ci res 4866855e09eSopenharmony_ci } 4876855e09eSopenharmony_ci} 4886855e09eSopenharmony_ci 4896855e09eSopenharmony_ci/// Matches a byte string with escaped characters. 4906855e09eSopenharmony_ci/// 4916855e09eSopenharmony_ci/// * The first argument matches the normal characters (it must not accept the control character) 4926855e09eSopenharmony_ci/// * The second argument is the control character (like `\` in most languages) 4936855e09eSopenharmony_ci/// * The third argument matches the escaped characters 4946855e09eSopenharmony_ci/// # Example 4956855e09eSopenharmony_ci/// ``` 4966855e09eSopenharmony_ci/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 4976855e09eSopenharmony_ci/// # use nom::character::complete::digit1; 4986855e09eSopenharmony_ci/// use nom::bytes::complete::escaped; 4996855e09eSopenharmony_ci/// use nom::character::complete::one_of; 5006855e09eSopenharmony_ci/// 5016855e09eSopenharmony_ci/// fn esc(s: &str) -> IResult<&str, &str> { 5026855e09eSopenharmony_ci/// escaped(digit1, '\\', one_of(r#""n\"#))(s) 5036855e09eSopenharmony_ci/// } 5046855e09eSopenharmony_ci/// 5056855e09eSopenharmony_ci/// assert_eq!(esc("123;"), Ok((";", "123"))); 5066855e09eSopenharmony_ci/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#))); 5076855e09eSopenharmony_ci/// ``` 5086855e09eSopenharmony_ci/// 5096855e09eSopenharmony_cipub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>( 5106855e09eSopenharmony_ci mut normal: F, 5116855e09eSopenharmony_ci control_char: char, 5126855e09eSopenharmony_ci mut escapable: G, 5136855e09eSopenharmony_ci) -> impl FnMut(Input) -> IResult<Input, Input, Error> 5146855e09eSopenharmony_ciwhere 5156855e09eSopenharmony_ci Input: Clone 5166855e09eSopenharmony_ci + crate::traits::Offset 5176855e09eSopenharmony_ci + InputLength 5186855e09eSopenharmony_ci + InputTake 5196855e09eSopenharmony_ci + InputTakeAtPosition 5206855e09eSopenharmony_ci + Slice<RangeFrom<usize>> 5216855e09eSopenharmony_ci + InputIter, 5226855e09eSopenharmony_ci <Input as InputIter>::Item: crate::traits::AsChar, 5236855e09eSopenharmony_ci F: Parser<Input, O1, Error>, 5246855e09eSopenharmony_ci G: Parser<Input, O2, Error>, 5256855e09eSopenharmony_ci Error: ParseError<Input>, 5266855e09eSopenharmony_ci{ 5276855e09eSopenharmony_ci use crate::traits::AsChar; 5286855e09eSopenharmony_ci 5296855e09eSopenharmony_ci move |input: Input| { 5306855e09eSopenharmony_ci let mut i = input.clone(); 5316855e09eSopenharmony_ci 5326855e09eSopenharmony_ci while i.input_len() > 0 { 5336855e09eSopenharmony_ci let current_len = i.input_len(); 5346855e09eSopenharmony_ci 5356855e09eSopenharmony_ci match normal.parse(i.clone()) { 5366855e09eSopenharmony_ci Ok((i2, _)) => { 5376855e09eSopenharmony_ci // return if we consumed everything or if the normal parser 5386855e09eSopenharmony_ci // does not consume anything 5396855e09eSopenharmony_ci if i2.input_len() == 0 { 5406855e09eSopenharmony_ci return Ok((input.slice(input.input_len()..), input)); 5416855e09eSopenharmony_ci } else if i2.input_len() == current_len { 5426855e09eSopenharmony_ci let index = input.offset(&i2); 5436855e09eSopenharmony_ci return Ok(input.take_split(index)); 5446855e09eSopenharmony_ci } else { 5456855e09eSopenharmony_ci i = i2; 5466855e09eSopenharmony_ci } 5476855e09eSopenharmony_ci } 5486855e09eSopenharmony_ci Err(Err::Error(_)) => { 5496855e09eSopenharmony_ci // unwrap() should be safe here since index < $i.input_len() 5506855e09eSopenharmony_ci if i.iter_elements().next().unwrap().as_char() == control_char { 5516855e09eSopenharmony_ci let next = control_char.len_utf8(); 5526855e09eSopenharmony_ci if next >= i.input_len() { 5536855e09eSopenharmony_ci return Err(Err::Error(Error::from_error_kind( 5546855e09eSopenharmony_ci input, 5556855e09eSopenharmony_ci ErrorKind::Escaped, 5566855e09eSopenharmony_ci ))); 5576855e09eSopenharmony_ci } else { 5586855e09eSopenharmony_ci match escapable.parse(i.slice(next..)) { 5596855e09eSopenharmony_ci Ok((i2, _)) => { 5606855e09eSopenharmony_ci if i2.input_len() == 0 { 5616855e09eSopenharmony_ci return Ok((input.slice(input.input_len()..), input)); 5626855e09eSopenharmony_ci } else { 5636855e09eSopenharmony_ci i = i2; 5646855e09eSopenharmony_ci } 5656855e09eSopenharmony_ci } 5666855e09eSopenharmony_ci Err(e) => return Err(e), 5676855e09eSopenharmony_ci } 5686855e09eSopenharmony_ci } 5696855e09eSopenharmony_ci } else { 5706855e09eSopenharmony_ci let index = input.offset(&i); 5716855e09eSopenharmony_ci if index == 0 { 5726855e09eSopenharmony_ci return Err(Err::Error(Error::from_error_kind( 5736855e09eSopenharmony_ci input, 5746855e09eSopenharmony_ci ErrorKind::Escaped, 5756855e09eSopenharmony_ci ))); 5766855e09eSopenharmony_ci } 5776855e09eSopenharmony_ci return Ok(input.take_split(index)); 5786855e09eSopenharmony_ci } 5796855e09eSopenharmony_ci } 5806855e09eSopenharmony_ci Err(e) => { 5816855e09eSopenharmony_ci return Err(e); 5826855e09eSopenharmony_ci } 5836855e09eSopenharmony_ci } 5846855e09eSopenharmony_ci } 5856855e09eSopenharmony_ci 5866855e09eSopenharmony_ci Ok((input.slice(input.input_len()..), input)) 5876855e09eSopenharmony_ci } 5886855e09eSopenharmony_ci} 5896855e09eSopenharmony_ci 5906855e09eSopenharmony_ci/// Matches a byte string with escaped characters. 5916855e09eSopenharmony_ci/// 5926855e09eSopenharmony_ci/// * The first argument matches the normal characters (it must not match the control character) 5936855e09eSopenharmony_ci/// * The second argument is the control character (like `\` in most languages) 5946855e09eSopenharmony_ci/// * The third argument matches the escaped characters and transforms them 5956855e09eSopenharmony_ci/// 5966855e09eSopenharmony_ci/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) 5976855e09eSopenharmony_ci/// 5986855e09eSopenharmony_ci/// ``` 5996855e09eSopenharmony_ci/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 6006855e09eSopenharmony_ci/// # use std::str::from_utf8; 6016855e09eSopenharmony_ci/// use nom::bytes::complete::{escaped_transform, tag}; 6026855e09eSopenharmony_ci/// use nom::character::complete::alpha1; 6036855e09eSopenharmony_ci/// use nom::branch::alt; 6046855e09eSopenharmony_ci/// use nom::combinator::value; 6056855e09eSopenharmony_ci/// 6066855e09eSopenharmony_ci/// fn parser(input: &str) -> IResult<&str, String> { 6076855e09eSopenharmony_ci/// escaped_transform( 6086855e09eSopenharmony_ci/// alpha1, 6096855e09eSopenharmony_ci/// '\\', 6106855e09eSopenharmony_ci/// alt(( 6116855e09eSopenharmony_ci/// value("\\", tag("\\")), 6126855e09eSopenharmony_ci/// value("\"", tag("\"")), 6136855e09eSopenharmony_ci/// value("\n", tag("n")), 6146855e09eSopenharmony_ci/// )) 6156855e09eSopenharmony_ci/// )(input) 6166855e09eSopenharmony_ci/// } 6176855e09eSopenharmony_ci/// 6186855e09eSopenharmony_ci/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd")))); 6196855e09eSopenharmony_ci/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd")))); 6206855e09eSopenharmony_ci/// ``` 6216855e09eSopenharmony_ci#[cfg(feature = "alloc")] 6226855e09eSopenharmony_ci#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] 6236855e09eSopenharmony_cipub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>( 6246855e09eSopenharmony_ci mut normal: F, 6256855e09eSopenharmony_ci control_char: char, 6266855e09eSopenharmony_ci mut transform: G, 6276855e09eSopenharmony_ci) -> impl FnMut(Input) -> IResult<Input, Output, Error> 6286855e09eSopenharmony_ciwhere 6296855e09eSopenharmony_ci Input: Clone 6306855e09eSopenharmony_ci + crate::traits::Offset 6316855e09eSopenharmony_ci + InputLength 6326855e09eSopenharmony_ci + InputTake 6336855e09eSopenharmony_ci + InputTakeAtPosition 6346855e09eSopenharmony_ci + Slice<RangeFrom<usize>> 6356855e09eSopenharmony_ci + InputIter, 6366855e09eSopenharmony_ci Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 6376855e09eSopenharmony_ci O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 6386855e09eSopenharmony_ci O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 6396855e09eSopenharmony_ci <Input as InputIter>::Item: crate::traits::AsChar, 6406855e09eSopenharmony_ci F: Parser<Input, O1, Error>, 6416855e09eSopenharmony_ci G: Parser<Input, O2, Error>, 6426855e09eSopenharmony_ci Error: ParseError<Input>, 6436855e09eSopenharmony_ci{ 6446855e09eSopenharmony_ci use crate::traits::AsChar; 6456855e09eSopenharmony_ci 6466855e09eSopenharmony_ci move |input: Input| { 6476855e09eSopenharmony_ci let mut index = 0; 6486855e09eSopenharmony_ci let mut res = input.new_builder(); 6496855e09eSopenharmony_ci 6506855e09eSopenharmony_ci let i = input.clone(); 6516855e09eSopenharmony_ci 6526855e09eSopenharmony_ci while index < i.input_len() { 6536855e09eSopenharmony_ci let current_len = i.input_len(); 6546855e09eSopenharmony_ci let remainder = i.slice(index..); 6556855e09eSopenharmony_ci match normal.parse(remainder.clone()) { 6566855e09eSopenharmony_ci Ok((i2, o)) => { 6576855e09eSopenharmony_ci o.extend_into(&mut res); 6586855e09eSopenharmony_ci if i2.input_len() == 0 { 6596855e09eSopenharmony_ci return Ok((i.slice(i.input_len()..), res)); 6606855e09eSopenharmony_ci } else if i2.input_len() == current_len { 6616855e09eSopenharmony_ci return Ok((remainder, res)); 6626855e09eSopenharmony_ci } else { 6636855e09eSopenharmony_ci index = input.offset(&i2); 6646855e09eSopenharmony_ci } 6656855e09eSopenharmony_ci } 6666855e09eSopenharmony_ci Err(Err::Error(_)) => { 6676855e09eSopenharmony_ci // unwrap() should be safe here since index < $i.input_len() 6686855e09eSopenharmony_ci if remainder.iter_elements().next().unwrap().as_char() == control_char { 6696855e09eSopenharmony_ci let next = index + control_char.len_utf8(); 6706855e09eSopenharmony_ci let input_len = input.input_len(); 6716855e09eSopenharmony_ci 6726855e09eSopenharmony_ci if next >= input_len { 6736855e09eSopenharmony_ci return Err(Err::Error(Error::from_error_kind( 6746855e09eSopenharmony_ci remainder, 6756855e09eSopenharmony_ci ErrorKind::EscapedTransform, 6766855e09eSopenharmony_ci ))); 6776855e09eSopenharmony_ci } else { 6786855e09eSopenharmony_ci match transform.parse(i.slice(next..)) { 6796855e09eSopenharmony_ci Ok((i2, o)) => { 6806855e09eSopenharmony_ci o.extend_into(&mut res); 6816855e09eSopenharmony_ci if i2.input_len() == 0 { 6826855e09eSopenharmony_ci return Ok((i.slice(i.input_len()..), res)); 6836855e09eSopenharmony_ci } else { 6846855e09eSopenharmony_ci index = input.offset(&i2); 6856855e09eSopenharmony_ci } 6866855e09eSopenharmony_ci } 6876855e09eSopenharmony_ci Err(e) => return Err(e), 6886855e09eSopenharmony_ci } 6896855e09eSopenharmony_ci } 6906855e09eSopenharmony_ci } else { 6916855e09eSopenharmony_ci if index == 0 { 6926855e09eSopenharmony_ci return Err(Err::Error(Error::from_error_kind( 6936855e09eSopenharmony_ci remainder, 6946855e09eSopenharmony_ci ErrorKind::EscapedTransform, 6956855e09eSopenharmony_ci ))); 6966855e09eSopenharmony_ci } 6976855e09eSopenharmony_ci return Ok((remainder, res)); 6986855e09eSopenharmony_ci } 6996855e09eSopenharmony_ci } 7006855e09eSopenharmony_ci Err(e) => return Err(e), 7016855e09eSopenharmony_ci } 7026855e09eSopenharmony_ci } 7036855e09eSopenharmony_ci Ok((input.slice(index..), res)) 7046855e09eSopenharmony_ci } 7056855e09eSopenharmony_ci} 7066855e09eSopenharmony_ci 7076855e09eSopenharmony_ci#[cfg(test)] 7086855e09eSopenharmony_cimod tests { 7096855e09eSopenharmony_ci use super::*; 7106855e09eSopenharmony_ci 7116855e09eSopenharmony_ci #[test] 7126855e09eSopenharmony_ci fn complete_take_while_m_n_utf8_all_matching() { 7136855e09eSopenharmony_ci let result: IResult<&str, &str> = 7146855e09eSopenharmony_ci super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); 7156855e09eSopenharmony_ci assert_eq!(result, Ok(("", "øn"))); 7166855e09eSopenharmony_ci } 7176855e09eSopenharmony_ci 7186855e09eSopenharmony_ci #[test] 7196855e09eSopenharmony_ci fn complete_take_while_m_n_utf8_all_matching_substring() { 7206855e09eSopenharmony_ci let result: IResult<&str, &str> = 7216855e09eSopenharmony_ci super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); 7226855e09eSopenharmony_ci assert_eq!(result, Ok(("n", "ø"))); 7236855e09eSopenharmony_ci } 7246855e09eSopenharmony_ci 7256855e09eSopenharmony_ci // issue #1336 "escaped hangs if normal parser accepts empty" 7266855e09eSopenharmony_ci fn escaped_string(input: &str) -> IResult<&str, &str> { 7276855e09eSopenharmony_ci use crate::character::complete::{alpha0, one_of}; 7286855e09eSopenharmony_ci escaped(alpha0, '\\', one_of("n"))(input) 7296855e09eSopenharmony_ci } 7306855e09eSopenharmony_ci 7316855e09eSopenharmony_ci // issue #1336 "escaped hangs if normal parser accepts empty" 7326855e09eSopenharmony_ci #[test] 7336855e09eSopenharmony_ci fn escaped_hang() { 7346855e09eSopenharmony_ci escaped_string("7").unwrap(); 7356855e09eSopenharmony_ci escaped_string("a7").unwrap(); 7366855e09eSopenharmony_ci } 7376855e09eSopenharmony_ci 7386855e09eSopenharmony_ci // issue ##1118 escaped does not work with empty string 7396855e09eSopenharmony_ci fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> { 7406855e09eSopenharmony_ci use crate::bytes::complete::*; 7416855e09eSopenharmony_ci use crate::character::complete::*; 7426855e09eSopenharmony_ci use crate::combinator::opt; 7436855e09eSopenharmony_ci use crate::sequence::delimited; 7446855e09eSopenharmony_ci 7456855e09eSopenharmony_ci delimited( 7466855e09eSopenharmony_ci char('"'), 7476855e09eSopenharmony_ci escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), 7486855e09eSopenharmony_ci char('"'), 7496855e09eSopenharmony_ci )(input) 7506855e09eSopenharmony_ci } 7516855e09eSopenharmony_ci 7526855e09eSopenharmony_ci #[test] 7536855e09eSopenharmony_ci fn escaped_hang_1118() { 7546855e09eSopenharmony_ci assert_eq!(unquote(r#""""#), Ok(("", ""))); 7556855e09eSopenharmony_ci } 7566855e09eSopenharmony_ci} 757