Coverage Report

Created: 2021-11-03 07:11

/rust/registry/src/github.com-1ecc6299db9ec823/nom-5.1.2/src/bytes/complete.rs
Line
Count
Source (jump to first uncovered line)
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
/// ```
30
19.2k
pub fn tag<'a, T: 'a, Input: 'a, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
31
19.2k
where
32
19.2k
  Input: InputTake + Compare<T>,
33
19.2k
  T: InputLength + Clone,
34
19.2k
{
35
19.2k
  move |i: Input| {
36
19.2k
    let tag_len = tag.input_len();
37
19.2k
    let t = tag.clone();
38
19.2k
    let res: IResult<_, _, Error> = match i.compare(t) {
39
3
      CompareResult::Ok => Ok(i.take_split(tag_len)),
40
      _ => {
41
19.2k
        let e: ErrorKind = ErrorKind::Tag;
42
19.2k
        Err(Err::Error(Error::from_error_kind(i, e)))
43
      }
44
    };
45
19.2k
    res
46
19.2k
  }
Unexecuted instantiation: nom::bytes::complete::tag::<&str, &[u8], (&[u8], nom::error::ErrorKind)>::{closure#0}
nom::bytes::complete::tag::<&str, &str, (&str, nom::error::ErrorKind)>::{closure#0}
Line
Count
Source
35
19.2k
  move |i: Input| {
36
19.2k
    let tag_len = tag.input_len();
37
19.2k
    let t = tag.clone();
38
19.2k
    let res: IResult<_, _, Error> = match i.compare(t) {
39
3
      CompareResult::Ok => Ok(i.take_split(tag_len)),
40
      _ => {
41
19.2k
        let e: ErrorKind = ErrorKind::Tag;
42
19.2k
        Err(Err::Error(Error::from_error_kind(i, e)))
43
      }
44
    };
45
19.2k
    res
46
19.2k
  }
47
19.2k
}
Unexecuted instantiation: nom::bytes::complete::tag::<&str, &[u8], (&[u8], nom::error::ErrorKind)>
nom::bytes::complete::tag::<&str, &str, (&str, nom::error::ErrorKind)>
Line
Count
Source
30
19.2k
pub fn tag<'a, T: 'a, Input: 'a, Error: ParseError<Input>>(tag: T) -> impl Fn(Input) -> IResult<Input, Input, Error>
31
19.2k
where
32
19.2k
  Input: InputTake + Compare<T>,
33
19.2k
  T: InputLength + Clone,
34
19.2k
{
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
19.2k
}
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
/// ```
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
/// ```
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
/// ```
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
/// ```
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
/// ```
209
0
pub fn take_while1<F, Input, Error: ParseError<Input>>(cond: F) -> impl Fn(Input) -> IResult<Input, Input, Error>
210
0
where
211
0
  Input: InputTakeAtPosition,
212
0
  F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
213
0
{
214
0
  move |i: Input| {
215
0
    let e: ErrorKind = ErrorKind::TakeWhile1;
216
0
    i.split_at_position1_complete(|c| !cond(c), e)
217
0
  }
218
0
}
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
/// ```
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
/// ```
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
/// ```
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
/// ```
378
0
pub fn take<C, Input, Error: ParseError<Input>>(count: C) -> impl Fn(Input) -> IResult<Input, Input, Error>
379
0
where
380
0
  Input: InputIter + InputTake,
381
0
  C: ToUsize,
382
0
{
383
0
  let c = count.to_usize();
384
0
  move |i: Input| match i.slice_index(c) {
385
0
    None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))),
386
0
    Some(index) => Ok(i.take_split(index)),
387
0
  }
388
0
}
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
/// ```
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
///
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)]
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")]
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")]
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]
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]
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
}