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