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