1//! Parsers recognizing bytes streams, complete input version 2 3use crate::error::ErrorKind; 4use crate::error::ParseError; 5use crate::internal::{Err, IResult, Parser}; 6use crate::lib::std::ops::RangeFrom; 7use crate::lib::std::result::Result::*; 8use crate::traits::{ 9 Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake, 10 InputTakeAtPosition, Slice, ToUsize, 11}; 12 13/// Recognizes a pattern 14/// 15/// The input data will be compared to the tag combinator's argument and will return the part of 16/// the input that matches the argument 17/// 18/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern 19/// # Example 20/// ```rust 21/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 22/// use nom::bytes::complete::tag; 23/// 24/// fn parser(s: &str) -> IResult<&str, &str> { 25/// tag("Hello")(s) 26/// } 27/// 28/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); 29/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); 30/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); 31/// ``` 32pub fn tag<T, Input, Error: ParseError<Input>>( 33 tag: T, 34) -> impl Fn(Input) -> IResult<Input, Input, Error> 35where 36 Input: InputTake + Compare<T>, 37 T: InputLength + Clone, 38{ 39 move |i: Input| { 40 let tag_len = tag.input_len(); 41 let t = tag.clone(); 42 let res: IResult<_, _, Error> = match i.compare(t) { 43 CompareResult::Ok => Ok(i.take_split(tag_len)), 44 _ => { 45 let e: ErrorKind = ErrorKind::Tag; 46 Err(Err::Error(Error::from_error_kind(i, e))) 47 } 48 }; 49 res 50 } 51} 52 53/// Recognizes a case insensitive pattern. 54/// 55/// The input data will be compared to the tag combinator's argument and will return the part of 56/// the input that matches the argument with no regard to case. 57/// 58/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern. 59/// # Example 60/// ```rust 61/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 62/// use nom::bytes::complete::tag_no_case; 63/// 64/// fn parser(s: &str) -> IResult<&str, &str> { 65/// tag_no_case("hello")(s) 66/// } 67/// 68/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello"))); 69/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello"))); 70/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO"))); 71/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag)))); 72/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag)))); 73/// ``` 74pub fn tag_no_case<T, Input, Error: ParseError<Input>>( 75 tag: T, 76) -> impl Fn(Input) -> IResult<Input, Input, Error> 77where 78 Input: InputTake + Compare<T>, 79 T: InputLength + Clone, 80{ 81 move |i: Input| { 82 let tag_len = tag.input_len(); 83 let t = tag.clone(); 84 85 let res: IResult<_, _, Error> = match (i).compare_no_case(t) { 86 CompareResult::Ok => Ok(i.take_split(tag_len)), 87 _ => { 88 let e: ErrorKind = ErrorKind::Tag; 89 Err(Err::Error(Error::from_error_kind(i, e))) 90 } 91 }; 92 res 93 } 94} 95 96/// Parse till certain characters are met. 97/// 98/// The parser will return the longest slice till one of the characters of the combinator's argument are met. 99/// 100/// It doesn't consume the matched character. 101/// 102/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met. 103/// # Example 104/// ```rust 105/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 106/// use nom::bytes::complete::is_not; 107/// 108/// fn not_space(s: &str) -> IResult<&str, &str> { 109/// is_not(" \t\r\n")(s) 110/// } 111/// 112/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,"))); 113/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes"))); 114/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace"))); 115/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot)))); 116/// ``` 117pub fn is_not<T, Input, Error: ParseError<Input>>( 118 arr: T, 119) -> impl Fn(Input) -> IResult<Input, Input, Error> 120where 121 Input: InputTakeAtPosition, 122 T: FindToken<<Input as InputTakeAtPosition>::Item>, 123{ 124 move |i: Input| { 125 let e: ErrorKind = ErrorKind::IsNot; 126 i.split_at_position1_complete(|c| arr.find_token(c), e) 127 } 128} 129 130/// Returns the longest slice of the matches the pattern. 131/// 132/// The parser will return the longest slice consisting of the characters in provided in the 133/// combinator's argument. 134/// 135/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met. 136/// # Example 137/// ```rust 138/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 139/// use nom::bytes::complete::is_a; 140/// 141/// fn hex(s: &str) -> IResult<&str, &str> { 142/// is_a("1234567890ABCDEF")(s) 143/// } 144/// 145/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123"))); 146/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF"))); 147/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE"))); 148/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E"))); 149/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA)))); 150/// ``` 151pub fn is_a<T, Input, Error: ParseError<Input>>( 152 arr: T, 153) -> impl Fn(Input) -> IResult<Input, Input, Error> 154where 155 Input: InputTakeAtPosition, 156 T: FindToken<<Input as InputTakeAtPosition>::Item>, 157{ 158 move |i: Input| { 159 let e: ErrorKind = ErrorKind::IsA; 160 i.split_at_position1_complete(|c| !arr.find_token(c), e) 161 } 162} 163 164/// Returns the longest input slice (if any) that matches the predicate. 165/// 166/// The parser will return the longest slice that matches the given predicate *(a function that 167/// takes the input and returns a bool)*. 168/// # Example 169/// ```rust 170/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 171/// use nom::bytes::complete::take_while; 172/// use nom::character::is_alphabetic; 173/// 174/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 175/// take_while(is_alphabetic)(s) 176/// } 177/// 178/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 179/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..]))); 180/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 181/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..]))); 182/// ``` 183pub fn take_while<F, Input, Error: ParseError<Input>>( 184 cond: F, 185) -> impl Fn(Input) -> IResult<Input, Input, Error> 186where 187 Input: InputTakeAtPosition, 188 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 189{ 190 move |i: Input| i.split_at_position_complete(|c| !cond(c)) 191} 192 193/// Returns the longest (at least 1) input slice that matches the predicate. 194/// 195/// The parser will return the longest slice that matches the given predicate *(a function that 196/// takes the input and returns a bool)*. 197/// 198/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met. 199/// # Example 200/// ```rust 201/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 202/// use nom::bytes::complete::take_while1; 203/// use nom::character::is_alphabetic; 204/// 205/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 206/// take_while1(is_alphabetic)(s) 207/// } 208/// 209/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 210/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 211/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1)))); 212/// ``` 213pub fn take_while1<F, Input, Error: ParseError<Input>>( 214 cond: F, 215) -> impl Fn(Input) -> IResult<Input, Input, Error> 216where 217 Input: InputTakeAtPosition, 218 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 219{ 220 move |i: Input| { 221 let e: ErrorKind = ErrorKind::TakeWhile1; 222 i.split_at_position1_complete(|c| !cond(c), e) 223 } 224} 225 226/// Returns the longest (m <= len <= n) input slice that matches the predicate. 227/// 228/// The parser will return the longest slice that matches the given predicate *(a function that 229/// takes the input and returns a bool)*. 230/// 231/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out 232/// of range (m <= len <= n). 233/// # Example 234/// ```rust 235/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 236/// use nom::bytes::complete::take_while_m_n; 237/// use nom::character::is_alphabetic; 238/// 239/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> { 240/// take_while_m_n(3, 6, is_alphabetic)(s) 241/// } 242/// 243/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..]))); 244/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..]))); 245/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..]))); 246/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN)))); 247/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN)))); 248/// ``` 249pub fn take_while_m_n<F, Input, Error: ParseError<Input>>( 250 m: usize, 251 n: usize, 252 cond: F, 253) -> impl Fn(Input) -> IResult<Input, Input, Error> 254where 255 Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>, 256 F: Fn(<Input as InputIter>::Item) -> bool, 257{ 258 move |i: Input| { 259 let input = i; 260 261 match input.position(|c| !cond(c)) { 262 Some(idx) => { 263 if idx >= m { 264 if idx <= n { 265 let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) { 266 Ok(input.take_split(index)) 267 } else { 268 Err(Err::Error(Error::from_error_kind( 269 input, 270 ErrorKind::TakeWhileMN, 271 ))) 272 }; 273 res 274 } else { 275 let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) { 276 Ok(input.take_split(index)) 277 } else { 278 Err(Err::Error(Error::from_error_kind( 279 input, 280 ErrorKind::TakeWhileMN, 281 ))) 282 }; 283 res 284 } 285 } else { 286 let e = ErrorKind::TakeWhileMN; 287 Err(Err::Error(Error::from_error_kind(input, e))) 288 } 289 } 290 None => { 291 let len = input.input_len(); 292 if len >= n { 293 match input.slice_index(n) { 294 Ok(index) => Ok(input.take_split(index)), 295 Err(_needed) => Err(Err::Error(Error::from_error_kind( 296 input, 297 ErrorKind::TakeWhileMN, 298 ))), 299 } 300 } else if len >= m && len <= n { 301 let res: IResult<_, _, Error> = Ok((input.slice(len..), input)); 302 res 303 } else { 304 let e = ErrorKind::TakeWhileMN; 305 Err(Err::Error(Error::from_error_kind(input, e))) 306 } 307 } 308 } 309 } 310} 311 312/// Returns the longest input slice (if any) till a predicate is met. 313/// 314/// The parser will return the longest slice till the given predicate *(a function that 315/// takes the input and returns a bool)*. 316/// # Example 317/// ```rust 318/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 319/// use nom::bytes::complete::take_till; 320/// 321/// fn till_colon(s: &str) -> IResult<&str, &str> { 322/// take_till(|c| c == ':')(s) 323/// } 324/// 325/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); 326/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed 327/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); 328/// assert_eq!(till_colon(""), Ok(("", ""))); 329/// ``` 330pub fn take_till<F, Input, Error: ParseError<Input>>( 331 cond: F, 332) -> impl Fn(Input) -> IResult<Input, Input, Error> 333where 334 Input: InputTakeAtPosition, 335 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 336{ 337 move |i: Input| i.split_at_position_complete(|c| cond(c)) 338} 339 340/// Returns the longest (at least 1) input slice till a predicate is met. 341/// 342/// The parser will return the longest slice till the given predicate *(a function that 343/// takes the input and returns a bool)*. 344/// 345/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the 346/// predicate matches the first input. 347/// # Example 348/// ```rust 349/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 350/// use nom::bytes::complete::take_till1; 351/// 352/// fn till_colon(s: &str) -> IResult<&str, &str> { 353/// take_till1(|c| c == ':')(s) 354/// } 355/// 356/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin"))); 357/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1)))); 358/// assert_eq!(till_colon("12345"), Ok(("", "12345"))); 359/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1)))); 360/// ``` 361pub fn take_till1<F, Input, Error: ParseError<Input>>( 362 cond: F, 363) -> impl Fn(Input) -> IResult<Input, Input, Error> 364where 365 Input: InputTakeAtPosition, 366 F: Fn(<Input as InputTakeAtPosition>::Item) -> bool, 367{ 368 move |i: Input| { 369 let e: ErrorKind = ErrorKind::TakeTill1; 370 i.split_at_position1_complete(|c| cond(c), e) 371 } 372} 373 374/// Returns an input slice containing the first N input elements (Input[..N]). 375/// 376/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument. 377/// # Example 378/// ```rust 379/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 380/// use nom::bytes::complete::take; 381/// 382/// fn take6(s: &str) -> IResult<&str, &str> { 383/// take(6usize)(s) 384/// } 385/// 386/// assert_eq!(take6("1234567"), Ok(("7", "123456"))); 387/// assert_eq!(take6("things"), Ok(("", "things"))); 388/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof)))); 389/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof)))); 390/// ``` 391/// 392/// The units that are taken will depend on the input type. For example, for a 393/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will 394/// take that many `u8`'s: 395/// 396/// ```rust 397/// use nom::error::Error; 398/// use nom::bytes::complete::take; 399/// 400/// assert_eq!(take::<_, _, Error<_>>(1usize)(""), Ok(("", ""))); 401/// assert_eq!(take::<_, _, Error<_>>(1usize)("".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref()))); 402/// ``` 403pub fn take<C, Input, Error: ParseError<Input>>( 404 count: C, 405) -> impl Fn(Input) -> IResult<Input, Input, Error> 406where 407 Input: InputIter + InputTake, 408 C: ToUsize, 409{ 410 let c = count.to_usize(); 411 move |i: Input| match i.slice_index(c) { 412 Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))), 413 Ok(index) => Ok(i.take_split(index)), 414 } 415} 416 417/// Returns the input slice up to the first occurrence of the pattern. 418/// 419/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` 420/// if the pattern wasn't met. 421/// # Example 422/// ```rust 423/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 424/// use nom::bytes::complete::take_until; 425/// 426/// fn until_eof(s: &str) -> IResult<&str, &str> { 427/// take_until("eof")(s) 428/// } 429/// 430/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); 431/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); 432/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); 433/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); 434/// ``` 435pub fn take_until<T, Input, Error: ParseError<Input>>( 436 tag: T, 437) -> impl Fn(Input) -> IResult<Input, Input, Error> 438where 439 Input: InputTake + FindSubstring<T>, 440 T: InputLength + Clone, 441{ 442 move |i: Input| { 443 let t = tag.clone(); 444 let res: IResult<_, _, Error> = match i.find_substring(t) { 445 None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 446 Some(index) => Ok(i.take_split(index)), 447 }; 448 res 449 } 450} 451 452/// Returns the non empty input slice up to the first occurrence of the pattern. 453/// 454/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))` 455/// if the pattern wasn't met. 456/// # Example 457/// ```rust 458/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult}; 459/// use nom::bytes::complete::take_until1; 460/// 461/// fn until_eof(s: &str) -> IResult<&str, &str> { 462/// take_until1("eof")(s) 463/// } 464/// 465/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world"))); 466/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil)))); 467/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil)))); 468/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1"))); 469/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil)))); 470/// ``` 471pub fn take_until1<T, Input, Error: ParseError<Input>>( 472 tag: T, 473) -> impl Fn(Input) -> IResult<Input, Input, Error> 474where 475 Input: InputTake + FindSubstring<T>, 476 T: InputLength + Clone, 477{ 478 move |i: Input| { 479 let t = tag.clone(); 480 let res: IResult<_, _, Error> = match i.find_substring(t) { 481 None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 482 Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))), 483 Some(index) => Ok(i.take_split(index)), 484 }; 485 res 486 } 487} 488 489/// Matches a byte string with escaped characters. 490/// 491/// * The first argument matches the normal characters (it must not accept the control character) 492/// * The second argument is the control character (like `\` in most languages) 493/// * The third argument matches the escaped characters 494/// # Example 495/// ``` 496/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 497/// # use nom::character::complete::digit1; 498/// use nom::bytes::complete::escaped; 499/// use nom::character::complete::one_of; 500/// 501/// fn esc(s: &str) -> IResult<&str, &str> { 502/// escaped(digit1, '\\', one_of(r#""n\"#))(s) 503/// } 504/// 505/// assert_eq!(esc("123;"), Ok((";", "123"))); 506/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#))); 507/// ``` 508/// 509pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>( 510 mut normal: F, 511 control_char: char, 512 mut escapable: G, 513) -> impl FnMut(Input) -> IResult<Input, Input, Error> 514where 515 Input: Clone 516 + crate::traits::Offset 517 + InputLength 518 + InputTake 519 + InputTakeAtPosition 520 + Slice<RangeFrom<usize>> 521 + InputIter, 522 <Input as InputIter>::Item: crate::traits::AsChar, 523 F: Parser<Input, O1, Error>, 524 G: Parser<Input, O2, Error>, 525 Error: ParseError<Input>, 526{ 527 use crate::traits::AsChar; 528 529 move |input: Input| { 530 let mut i = input.clone(); 531 532 while i.input_len() > 0 { 533 let current_len = i.input_len(); 534 535 match normal.parse(i.clone()) { 536 Ok((i2, _)) => { 537 // return if we consumed everything or if the normal parser 538 // does not consume anything 539 if i2.input_len() == 0 { 540 return Ok((input.slice(input.input_len()..), input)); 541 } else if i2.input_len() == current_len { 542 let index = input.offset(&i2); 543 return Ok(input.take_split(index)); 544 } else { 545 i = i2; 546 } 547 } 548 Err(Err::Error(_)) => { 549 // unwrap() should be safe here since index < $i.input_len() 550 if i.iter_elements().next().unwrap().as_char() == control_char { 551 let next = control_char.len_utf8(); 552 if next >= i.input_len() { 553 return Err(Err::Error(Error::from_error_kind( 554 input, 555 ErrorKind::Escaped, 556 ))); 557 } else { 558 match escapable.parse(i.slice(next..)) { 559 Ok((i2, _)) => { 560 if i2.input_len() == 0 { 561 return Ok((input.slice(input.input_len()..), input)); 562 } else { 563 i = i2; 564 } 565 } 566 Err(e) => return Err(e), 567 } 568 } 569 } else { 570 let index = input.offset(&i); 571 if index == 0 { 572 return Err(Err::Error(Error::from_error_kind( 573 input, 574 ErrorKind::Escaped, 575 ))); 576 } 577 return Ok(input.take_split(index)); 578 } 579 } 580 Err(e) => { 581 return Err(e); 582 } 583 } 584 } 585 586 Ok((input.slice(input.input_len()..), input)) 587 } 588} 589 590/// Matches a byte string with escaped characters. 591/// 592/// * The first argument matches the normal characters (it must not match the control character) 593/// * The second argument is the control character (like `\` in most languages) 594/// * The third argument matches the escaped characters and transforms them 595/// 596/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character) 597/// 598/// ``` 599/// # use nom::{Err, error::ErrorKind, Needed, IResult}; 600/// # use std::str::from_utf8; 601/// use nom::bytes::complete::{escaped_transform, tag}; 602/// use nom::character::complete::alpha1; 603/// use nom::branch::alt; 604/// use nom::combinator::value; 605/// 606/// fn parser(input: &str) -> IResult<&str, String> { 607/// escaped_transform( 608/// alpha1, 609/// '\\', 610/// alt(( 611/// value("\\", tag("\\")), 612/// value("\"", tag("\"")), 613/// value("\n", tag("n")), 614/// )) 615/// )(input) 616/// } 617/// 618/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd")))); 619/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd")))); 620/// ``` 621#[cfg(feature = "alloc")] 622#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))] 623pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>( 624 mut normal: F, 625 control_char: char, 626 mut transform: G, 627) -> impl FnMut(Input) -> IResult<Input, Output, Error> 628where 629 Input: Clone 630 + crate::traits::Offset 631 + InputLength 632 + InputTake 633 + InputTakeAtPosition 634 + Slice<RangeFrom<usize>> 635 + InputIter, 636 Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 637 O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 638 O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>, 639 <Input as InputIter>::Item: crate::traits::AsChar, 640 F: Parser<Input, O1, Error>, 641 G: Parser<Input, O2, Error>, 642 Error: ParseError<Input>, 643{ 644 use crate::traits::AsChar; 645 646 move |input: Input| { 647 let mut index = 0; 648 let mut res = input.new_builder(); 649 650 let i = input.clone(); 651 652 while index < i.input_len() { 653 let current_len = i.input_len(); 654 let remainder = i.slice(index..); 655 match normal.parse(remainder.clone()) { 656 Ok((i2, o)) => { 657 o.extend_into(&mut res); 658 if i2.input_len() == 0 { 659 return Ok((i.slice(i.input_len()..), res)); 660 } else if i2.input_len() == current_len { 661 return Ok((remainder, res)); 662 } else { 663 index = input.offset(&i2); 664 } 665 } 666 Err(Err::Error(_)) => { 667 // unwrap() should be safe here since index < $i.input_len() 668 if remainder.iter_elements().next().unwrap().as_char() == control_char { 669 let next = index + control_char.len_utf8(); 670 let input_len = input.input_len(); 671 672 if next >= input_len { 673 return Err(Err::Error(Error::from_error_kind( 674 remainder, 675 ErrorKind::EscapedTransform, 676 ))); 677 } else { 678 match transform.parse(i.slice(next..)) { 679 Ok((i2, o)) => { 680 o.extend_into(&mut res); 681 if i2.input_len() == 0 { 682 return Ok((i.slice(i.input_len()..), res)); 683 } else { 684 index = input.offset(&i2); 685 } 686 } 687 Err(e) => return Err(e), 688 } 689 } 690 } else { 691 if index == 0 { 692 return Err(Err::Error(Error::from_error_kind( 693 remainder, 694 ErrorKind::EscapedTransform, 695 ))); 696 } 697 return Ok((remainder, res)); 698 } 699 } 700 Err(e) => return Err(e), 701 } 702 } 703 Ok((input.slice(index..), res)) 704 } 705} 706 707#[cfg(test)] 708mod tests { 709 use super::*; 710 711 #[test] 712 fn complete_take_while_m_n_utf8_all_matching() { 713 let result: IResult<&str, &str> = 714 super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn"); 715 assert_eq!(result, Ok(("", "øn"))); 716 } 717 718 #[test] 719 fn complete_take_while_m_n_utf8_all_matching_substring() { 720 let result: IResult<&str, &str> = 721 super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn"); 722 assert_eq!(result, Ok(("n", "ø"))); 723 } 724 725 // issue #1336 "escaped hangs if normal parser accepts empty" 726 fn escaped_string(input: &str) -> IResult<&str, &str> { 727 use crate::character::complete::{alpha0, one_of}; 728 escaped(alpha0, '\\', one_of("n"))(input) 729 } 730 731 // issue #1336 "escaped hangs if normal parser accepts empty" 732 #[test] 733 fn escaped_hang() { 734 escaped_string("7").unwrap(); 735 escaped_string("a7").unwrap(); 736 } 737 738 // issue ##1118 escaped does not work with empty string 739 fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> { 740 use crate::bytes::complete::*; 741 use crate::character::complete::*; 742 use crate::combinator::opt; 743 use crate::sequence::delimited; 744 745 delimited( 746 char('"'), 747 escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)), 748 char('"'), 749 )(input) 750 } 751 752 #[test] 753 fn escaped_hang_1118() { 754 assert_eq!(unquote(r#""""#), Ok(("", ""))); 755 } 756} 757