Coverage Report

Created: 2026-01-10 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nom-8.0.0/src/bytes/complete.rs
Line
Count
Source
1
//! Parsers recognizing bytes streams, complete input version
2
3
use core::marker::PhantomData;
4
5
use crate::error::ParseError;
6
use crate::internal::{IResult, Parser};
7
use crate::traits::{Compare, FindSubstring, FindToken, ToUsize};
8
use crate::Complete;
9
use crate::Emit;
10
use crate::Input;
11
use crate::OutputM;
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
/// ```
32
0
pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
33
0
where
34
0
  I: Input + Compare<T>,
35
0
  T: Input + Clone,
36
{
37
0
  move |i: I| {
38
0
    let mut parser = super::Tag {
39
0
      tag: tag.clone(),
40
0
      e: PhantomData,
41
0
    };
42
43
0
    parser.process::<OutputM<Emit, Emit, Complete>>(i)
44
0
  }
Unexecuted instantiation: nom::bytes::complete::tag::<&str, &str, nom::error::Error<&str>>::{closure#0}
Unexecuted instantiation: nom::bytes::complete::tag::<_, _, _>::{closure#0}
45
0
}
Unexecuted instantiation: nom::bytes::complete::tag::<&str, &str, nom::error::Error<&str>>
Unexecuted instantiation: nom::bytes::complete::tag::<_, _, _>
46
47
/// Recognizes a case insensitive pattern.
48
///
49
/// The input data will be compared to the tag combinator's argument and will return the part of
50
/// the input that matches the argument with no regard to case.
51
///
52
/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern.
53
/// # Example
54
/// ```rust
55
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
56
/// use nom::bytes::complete::tag_no_case;
57
///
58
/// fn parser(s: &str) -> IResult<&str, &str> {
59
///   tag_no_case("hello")(s)
60
/// }
61
///
62
/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
63
/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
64
/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
65
/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
66
/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
67
/// ```
68
0
pub fn tag_no_case<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
69
0
where
70
0
  I: Input + Compare<T>,
71
0
  T: Input + Clone,
72
{
73
0
  move |i: I| {
74
0
    let mut parser = super::TagNoCase {
75
0
      tag: tag.clone(),
76
0
      e: PhantomData,
77
0
    };
78
79
0
    parser.process::<OutputM<Emit, Emit, Complete>>(i)
80
0
  }
81
0
}
82
83
/// Parse till certain characters are met.
84
///
85
/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
86
///
87
/// It doesn't consume the matched character.
88
///
89
/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met.
90
/// # Example
91
/// ```rust
92
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
93
/// use nom::bytes::complete::is_not;
94
///
95
/// fn not_space(s: &str) -> IResult<&str, &str> {
96
///   is_not(" \t\r\n")(s)
97
/// }
98
///
99
/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
100
/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
101
/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
102
/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot))));
103
/// ```
104
0
pub fn is_not<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
105
0
where
106
0
  I: Input,
107
0
  T: FindToken<<I as Input>::Item>,
108
{
109
0
  let mut parser = super::is_not(arr);
110
111
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
112
0
}
113
114
/// Returns the longest slice of the matches the pattern.
115
///
116
/// The parser will return the longest slice consisting of the characters in provided in the
117
/// combinator's argument.
118
///
119
/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met.
120
/// # Example
121
/// ```rust
122
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
123
/// use nom::bytes::complete::is_a;
124
///
125
/// fn hex(s: &str) -> IResult<&str, &str> {
126
///   is_a("1234567890ABCDEF")(s)
127
/// }
128
///
129
/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
130
/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
131
/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
132
/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
133
/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA))));
134
/// ```
135
0
pub fn is_a<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
136
0
where
137
0
  I: Input,
138
0
  T: FindToken<<I as Input>::Item>,
139
{
140
0
  let mut parser = super::is_a(arr);
141
142
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
143
0
}
144
145
/// Returns the longest input slice (if any) that matches the predicate.
146
///
147
/// The parser will return the longest slice that matches the given predicate *(a function that
148
/// takes the input and returns a bool)*.
149
/// # Example
150
/// ```rust
151
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
152
/// use nom::bytes::complete::take_while;
153
/// use nom::AsChar;
154
///
155
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
156
///   take_while(AsChar::is_alpha)(s)
157
/// }
158
///
159
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
160
/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
161
/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
162
/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
163
/// ```
164
0
pub fn take_while<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
165
0
where
166
0
  I: Input,
167
0
  F: Fn(<I as Input>::Item) -> bool,
168
{
169
0
  let mut parser = super::take_while(cond);
170
171
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
172
0
}
173
174
/// Returns the longest (at least 1) input slice that matches the predicate.
175
///
176
/// The parser will return the longest slice that matches the given predicate *(a function that
177
/// takes the input and returns a bool)*.
178
///
179
/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
180
/// # Example
181
/// ```rust
182
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
183
/// use nom::bytes::complete::take_while1;
184
/// use nom::AsChar;
185
///
186
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
187
///   take_while1(AsChar::is_alpha)(s)
188
/// }
189
///
190
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
191
/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
192
/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
193
/// ```
194
0
pub fn take_while1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
195
0
where
196
0
  I: Input,
197
0
  F: Fn(<I as Input>::Item) -> bool,
198
{
199
0
  let mut parser = super::take_while1(cond);
200
201
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
202
0
}
203
204
/// Returns the longest (m <= len <= n) input slice that matches the predicate.
205
///
206
/// The parser will return the longest slice that matches the given predicate *(a function that
207
/// takes the input and returns a bool)*.
208
///
209
/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out
210
/// of range (m <= len <= n).
211
/// # Example
212
/// ```rust
213
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
214
/// use nom::bytes::complete::take_while_m_n;
215
/// use nom::AsChar;
216
///
217
/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
218
///   take_while_m_n(3, 6, AsChar::is_alpha)(s)
219
/// }
220
///
221
/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
222
/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
223
/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
224
/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN))));
225
/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
226
/// ```
227
0
pub fn take_while_m_n<F, I, Error: ParseError<I>>(
228
0
  m: usize,
229
0
  n: usize,
230
0
  cond: F,
231
0
) -> impl FnMut(I) -> IResult<I, I, Error>
232
0
where
233
0
  I: Input,
234
0
  F: Fn(<I as Input>::Item) -> bool,
235
{
236
0
  let mut parser = super::take_while_m_n(m, n, cond);
237
238
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
239
0
}
240
241
/// Returns the longest input slice (if any) till a predicate is met.
242
///
243
/// The parser will return the longest slice till the given predicate *(a function that
244
/// takes the input and returns a bool)*.
245
/// # Example
246
/// ```rust
247
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
248
/// use nom::bytes::complete::take_till;
249
///
250
/// fn till_colon(s: &str) -> IResult<&str, &str> {
251
///   take_till(|c| c == ':')(s)
252
/// }
253
///
254
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
255
/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
256
/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
257
/// assert_eq!(till_colon(""), Ok(("", "")));
258
/// ```
259
#[allow(clippy::redundant_closure)]
260
0
pub fn take_till<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
261
0
where
262
0
  I: Input,
263
0
  F: Fn(<I as Input>::Item) -> bool,
264
{
265
0
  let mut parser = super::take_till(cond);
266
267
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
268
0
}
269
270
/// Returns the longest (at least 1) input slice till a predicate is met.
271
///
272
/// The parser will return the longest slice till the given predicate *(a function that
273
/// takes the input and returns a bool)*.
274
///
275
/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the
276
/// predicate matches the first input.
277
/// # Example
278
/// ```rust
279
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
280
/// use nom::bytes::complete::take_till1;
281
///
282
/// fn till_colon(s: &str) -> IResult<&str, &str> {
283
///   take_till1(|c| c == ':')(s)
284
/// }
285
///
286
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
287
/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
288
/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
289
/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
290
/// ```
291
#[allow(clippy::redundant_closure)]
292
0
pub fn take_till1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
293
0
where
294
0
  I: Input,
295
0
  F: Fn(<I as Input>::Item) -> bool,
296
{
297
0
  let mut parser = super::take_till1(cond);
298
299
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
300
0
}
301
302
/// Returns an input slice containing the first N input elements (Input[..N]).
303
///
304
/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument.
305
/// # Example
306
/// ```rust
307
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
308
/// use nom::bytes::complete::take;
309
///
310
/// fn take6(s: &str) -> IResult<&str, &str> {
311
///   take(6usize)(s)
312
/// }
313
///
314
/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
315
/// assert_eq!(take6("things"), Ok(("", "things")));
316
/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
317
/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
318
/// ```
319
///
320
/// The units that are taken will depend on the input type. For example, for a
321
/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
322
/// take that many `u8`'s:
323
///
324
/// ```rust
325
/// use nom::error::Error;
326
/// use nom::bytes::complete::take;
327
///
328
/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙")));
329
/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
330
/// ```
331
0
pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl FnMut(I) -> IResult<I, I, Error>
332
0
where
333
0
  I: Input,
334
0
  C: ToUsize,
335
{
336
0
  let mut parser = super::take(count);
337
338
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
339
0
}
340
341
/// Returns the input slice up to the first occurrence of the pattern.
342
///
343
/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
344
/// if the pattern wasn't met.
345
/// # Example
346
/// ```rust
347
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
348
/// use nom::bytes::complete::take_until;
349
///
350
/// fn until_eof(s: &str) -> IResult<&str, &str> {
351
///   take_until("eof")(s)
352
/// }
353
///
354
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
355
/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
356
/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
357
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
358
/// ```
359
0
pub fn take_until<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
360
0
where
361
0
  I: Input + FindSubstring<T>,
362
0
  T: Input + Clone,
363
{
364
0
  let mut parser = super::take_until(tag);
365
366
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
367
0
}
368
369
/// Returns the non empty input slice up to the first occurrence of the pattern.
370
///
371
/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
372
/// if the pattern wasn't met.
373
/// # Example
374
/// ```rust
375
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
376
/// use nom::bytes::complete::take_until1;
377
///
378
/// fn until_eof(s: &str) -> IResult<&str, &str> {
379
///   take_until1("eof")(s)
380
/// }
381
///
382
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
383
/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
384
/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
385
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
386
/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
387
/// ```
388
0
pub fn take_until1<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
389
0
where
390
0
  I: Input + FindSubstring<T>,
391
0
  T: Input + Clone,
392
{
393
0
  let mut parser = super::take_until1(tag);
394
395
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
396
0
}
397
398
/// Matches a byte string with escaped characters.
399
///
400
/// * The first argument matches the normal characters (it must not accept the control character)
401
/// * The second argument is the control character (like `\` in most languages)
402
/// * The third argument matches the escaped characters
403
/// # Example
404
/// ```
405
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
406
/// # use nom::character::complete::digit1;
407
/// use nom::bytes::complete::escaped;
408
/// use nom::character::complete::one_of;
409
///
410
/// fn esc(s: &str) -> IResult<&str, &str> {
411
///   escaped(digit1, '\\', one_of(r#""n\"#))(s)
412
/// }
413
///
414
/// assert_eq!(esc("123;"), Ok((";", "123")));
415
/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#)));
416
/// ```
417
///
418
0
pub fn escaped<'a, I, Error, F, G>(
419
0
  normal: F,
420
0
  control_char: char,
421
0
  escapable: G,
422
0
) -> impl FnMut(I) -> IResult<I, I, Error>
423
0
where
424
0
  I: Clone + crate::traits::Offset + Input + 'a,
425
0
  <I as Input>::Item: crate::traits::AsChar,
426
0
  F: Parser<I, Error = Error>,
427
0
  G: Parser<I, Error = Error>,
428
0
  Error: ParseError<I>,
429
{
430
0
  let mut parser = super::escaped(normal, control_char, escapable);
431
432
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
433
0
}
434
435
/// Matches a byte string with escaped characters.
436
///
437
/// * The first argument matches the normal characters (it must not match the control character)
438
/// * The second argument is the control character (like `\` in most languages)
439
/// * The third argument matches the escaped characters and transforms them
440
///
441
/// As an example, the chain `abc\tdef` could be `abc    def` (it also consumes the control character)
442
///
443
/// ```
444
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
445
/// # use std::str::from_utf8;
446
/// use nom::bytes::complete::{escaped_transform, tag};
447
/// use nom::character::complete::alpha1;
448
/// use nom::branch::alt;
449
/// use nom::combinator::value;
450
///
451
/// fn parser(input: &str) -> IResult<&str, String> {
452
///   escaped_transform(
453
///     alpha1,
454
///     '\\',
455
///     alt((
456
///       value("\\", tag("\\")),
457
///       value("\"", tag("\"")),
458
///       value("\n", tag("n")),
459
///     ))
460
///   )(input)
461
/// }
462
///
463
/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd"))));
464
/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd"))));
465
/// ```
466
#[cfg(feature = "alloc")]
467
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
468
0
pub fn escaped_transform<I, Error, F, G, O1, O2, ExtendItem, Output>(
469
0
  normal: F,
470
0
  control_char: char,
471
0
  transform: G,
472
0
) -> impl FnMut(I) -> IResult<I, Output, Error>
473
0
where
474
0
  I: Clone + crate::traits::Offset + Input,
475
0
  I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
476
0
  O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
477
0
  O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
478
0
  <I as Input>::Item: crate::traits::AsChar,
479
0
  F: Parser<I, Output = O1, Error = Error>,
480
0
  G: Parser<I, Output = O2, Error = Error>,
481
0
  Error: ParseError<I>,
482
{
483
0
  let mut parser = super::escaped_transform(normal, control_char, transform);
484
485
0
  move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
486
0
}
487
488
#[cfg(test)]
489
mod tests {
490
  use super::*;
491
  use crate::error::ErrorKind;
492
  use crate::AsChar;
493
  use crate::Err;
494
495
  #[test]
496
  fn complete_take_while_m_n_utf8_all_matching() {
497
    let result: IResult<&str, &str> =
498
      super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn");
499
    assert_eq!(result, Ok(("", "øn")));
500
  }
501
502
  #[test]
503
  fn complete_take_while_m_n_utf8_all_matching_substring() {
504
    let result: IResult<&str, &str> =
505
      super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn");
506
    assert_eq!(result, Ok(("n", "ø")));
507
  }
508
509
  // issue #1336 "escaped hangs if normal parser accepts empty"
510
  fn escaped_string(input: &str) -> IResult<&str, &str> {
511
    use crate::character::complete::{alpha0, one_of};
512
    escaped(alpha0, '\\', one_of("n"))(input)
513
  }
514
515
  // issue #1336 "escaped hangs if normal parser accepts empty"
516
  #[test]
517
  fn escaped_hang() {
518
    escaped_string("7").unwrap();
519
    escaped_string("a7").unwrap();
520
  }
521
522
  // issue ##1118 escaped does not work with empty string
523
  fn unquote(input: &str) -> IResult<&str, &str> {
524
    use crate::bytes::complete::*;
525
    use crate::character::complete::*;
526
    use crate::combinator::opt;
527
    use crate::sequence::delimited;
528
529
    delimited(
530
      char('"'),
531
      escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
532
      char('"'),
533
    )
534
    .parse(input)
535
  }
536
537
  #[test]
538
  fn escaped_hang_1118() {
539
    assert_eq!(unquote(r#""""#), Ok(("", "")));
540
  }
541
542
  // issue #1630 take_while_m_n is invalid for multi-byte UTF-8 characters
543
  #[test]
544
  fn complete_take_while_m_n_multibyte() {
545
    use crate::error::Error;
546
547
    fn multi_byte_chars(s: &str, m: usize, n: usize) -> IResult<&str, &str> {
548
      take_while_m_n(m, n, |c: char| c.len() > 1)(s)
549
    }
550
551
    assert_eq!(multi_byte_chars("€ latin", 0, 64), Ok((" latin", "€")));
552
    assert_eq!(multi_byte_chars("𝄠 latin", 0, 1), Ok((" latin", "𝄠")));
553
    assert_eq!(multi_byte_chars("باب latin", 0, 64), Ok((" latin", "باب")));
554
    assert_eq!(
555
      multi_byte_chars("💣💢ᾠ latin", 3, 3),
556
      Ok((" latin", "💣💢ᾠ"))
557
    );
558
    assert_eq!(multi_byte_chars("latin", 0, 64), Ok(("latin", "")));
559
    assert_eq!(multi_byte_chars("باب", 1, 3), Ok(("", "باب")));
560
    assert_eq!(multi_byte_chars("باب", 1, 2), Ok(("ب", "با")));
561
    assert_eq!(
562
      multi_byte_chars("latin", 1, 64),
563
      Err(Err::Error(Error::new("latin", ErrorKind::TakeWhileMN)))
564
    );
565
  }
566
}