nom8/bytes/
complete.rs

1//! Parsers recognizing bytes streams, complete input version
2
3#![allow(deprecated)]
4
5use crate::error::ErrorKind;
6use crate::error::ParseError;
7use crate::input::{
8  Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake,
9  InputTakeAtPosition, IntoOutput, Slice, ToUsize,
10};
11use crate::lib::std::ops::RangeFrom;
12use crate::lib::std::result::Result::*;
13use crate::IntoOutputIResult;
14use crate::{Err, IResult, Parser};
15
16pub(crate) fn any<I, E: ParseError<I>>(input: I) -> IResult<I, <I as InputIter>::Item, E>
17where
18  I: InputIter + InputLength + Slice<RangeFrom<usize>>,
19{
20  let mut it = input.iter_indices();
21  match it.next() {
22    None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))),
23    Some((_, c)) => match it.next() {
24      None => Ok((input.slice(input.input_len()..), c)),
25      Some((idx, _)) => Ok((input.slice(idx..), c)),
26    },
27  }
28}
29
30/// Recognizes a pattern
31///
32/// The input data will be compared to the tag combinator's argument and will return the part of
33/// the input that matches the argument
34///
35/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern
36/// # Example
37/// ```rust
38/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
39/// use nom8::bytes::complete::tag;
40///
41/// fn parser(s: &str) -> IResult<&str, &str> {
42///   tag("Hello")(s)
43/// }
44///
45/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
46/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
47/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
48/// ```
49///
50/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag`][crate::bytes::tag]
51#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::tag`")]
52pub fn tag<T, Input, Error: ParseError<Input>>(
53  tag: T,
54) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
55where
56  Input: InputTake + Compare<T>,
57  Input: IntoOutput,
58  T: InputLength + Clone,
59{
60  move |i: Input| tag_internal(i, tag.clone())
61}
62
63pub(crate) fn tag_internal<T, Input, Error: ParseError<Input>>(
64  i: Input,
65  t: T,
66) -> IResult<Input, <Input as IntoOutput>::Output, Error>
67where
68  Input: InputTake + Compare<T>,
69  Input: IntoOutput,
70  T: InputLength,
71{
72  let tag_len = t.input_len();
73  let res: IResult<_, _, Error> = match i.compare(t) {
74    CompareResult::Ok => Ok(i.take_split(tag_len)),
75    _ => {
76      let e: ErrorKind = ErrorKind::Tag;
77      Err(Err::Error(Error::from_error_kind(i, e)))
78    }
79  };
80  res.into_output()
81}
82
83/// Recognizes a case insensitive pattern.
84///
85/// The input data will be compared to the tag combinator's argument and will return the part of
86/// the input that matches the argument with no regard to case.
87///
88/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern.
89/// # Example
90/// ```rust
91/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
92/// use nom8::bytes::complete::tag_no_case;
93///
94/// fn parser(s: &str) -> IResult<&str, &str> {
95///   tag_no_case("hello")(s)
96/// }
97///
98/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
99/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
100/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
101/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
102/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
103/// ```
104///
105/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag_no_case`][crate::bytes::tag_no_case]
106#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::tag_no_case`")]
107pub fn tag_no_case<T, Input, Error: ParseError<Input>>(
108  tag: T,
109) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
110where
111  Input: InputTake + Compare<T>,
112  Input: IntoOutput,
113  T: InputLength + Clone,
114{
115  move |i: Input| tag_no_case_internal(i, tag.clone())
116}
117
118pub(crate) fn tag_no_case_internal<T, Input, Error: ParseError<Input>>(
119  i: Input,
120  t: T,
121) -> IResult<Input, <Input as IntoOutput>::Output, Error>
122where
123  Input: InputTake + Compare<T>,
124  Input: IntoOutput,
125  T: InputLength,
126{
127  let tag_len = t.input_len();
128
129  let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
130    CompareResult::Ok => Ok(i.take_split(tag_len)),
131    _ => {
132      let e: ErrorKind = ErrorKind::Tag;
133      Err(Err::Error(Error::from_error_kind(i, e)))
134    }
135  };
136  res.into_output()
137}
138
139pub(crate) fn one_of_internal<I, T, E: ParseError<I>>(
140  input: I,
141  list: &T,
142) -> IResult<I, <I as InputIter>::Item, E>
143where
144  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
145  <I as InputIter>::Item: Copy,
146  T: FindToken<<I as InputIter>::Item>,
147{
148  let mut it = input.iter_indices();
149  match it.next() {
150    Some((_, c)) if list.find_token(c) => match it.next() {
151      None => Ok((input.slice(input.input_len()..), c)),
152      Some((idx, _)) => Ok((input.slice(idx..), c)),
153    },
154    Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::OneOf))),
155    None => Err(Err::Error(E::from_error_kind(input, ErrorKind::OneOf))),
156  }
157}
158
159pub(crate) fn none_of_internal<I, T, E: ParseError<I>>(
160  input: I,
161  list: &T,
162) -> IResult<I, <I as InputIter>::Item, E>
163where
164  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
165  <I as InputIter>::Item: Copy,
166  T: FindToken<<I as InputIter>::Item>,
167{
168  let mut it = input.iter_indices();
169  match it.next() {
170    Some((_, c)) if !list.find_token(c) => match it.next() {
171      None => Ok((input.slice(input.input_len()..), c)),
172      Some((idx, _)) => Ok((input.slice(idx..), c)),
173    },
174    Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::NoneOf))),
175    None => Err(Err::Error(E::from_error_kind(input, ErrorKind::NoneOf))),
176  }
177}
178
179/// Parse till certain characters are met.
180///
181/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
182///
183/// It doesn't consume the matched character.
184///
185/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met.
186/// # Example
187/// ```rust
188/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
189/// use nom8::bytes::complete::is_not;
190///
191/// fn not_space(s: &str) -> IResult<&str, &str> {
192///   is_not(" \t\r\n")(s)
193/// }
194///
195/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
196/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
197/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
198/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot))));
199/// ```
200///
201/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1]
202#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till1`")]
203pub fn is_not<T, Input, Error: ParseError<Input>>(
204  arr: T,
205) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
206where
207  Input: InputTakeAtPosition,
208  Input: IntoOutput,
209  T: FindToken<<Input as InputTakeAtPosition>::Item>,
210{
211  move |i: Input| is_not_internal(i, &arr)
212}
213
214pub(crate) fn is_not_internal<T, Input, Error: ParseError<Input>>(
215  i: Input,
216  arr: &T,
217) -> IResult<Input, <Input as IntoOutput>::Output, Error>
218where
219  Input: InputTakeAtPosition,
220  Input: IntoOutput,
221  T: FindToken<<Input as InputTakeAtPosition>::Item>,
222{
223  let e: ErrorKind = ErrorKind::IsNot;
224  i.split_at_position1_complete(|c| arr.find_token(c), e)
225    .into_output()
226}
227
228/// Returns the longest slice of the matches the pattern.
229///
230/// The parser will return the longest slice consisting of the characters in provided in the
231/// combinator's argument.
232///
233/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met.
234/// # Example
235/// ```rust
236/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
237/// use nom8::bytes::complete::is_a;
238///
239/// fn hex(s: &str) -> IResult<&str, &str> {
240///   is_a("1234567890ABCDEF")(s)
241/// }
242///
243/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
244/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
245/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
246/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
247/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA))));
248/// ```
249///
250/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1`]
251#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while1`")]
252pub fn is_a<T, Input, Error: ParseError<Input>>(
253  arr: T,
254) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
255where
256  Input: InputTakeAtPosition,
257  Input: IntoOutput,
258  T: FindToken<<Input as InputTakeAtPosition>::Item>,
259{
260  move |i: Input| is_a_internal(i, &arr)
261}
262
263pub(crate) fn is_a_internal<T, Input, Error: ParseError<Input>>(
264  i: Input,
265  arr: &T,
266) -> IResult<Input, <Input as IntoOutput>::Output, Error>
267where
268  Input: InputTakeAtPosition,
269  Input: IntoOutput,
270  T: FindToken<<Input as InputTakeAtPosition>::Item>,
271{
272  let e: ErrorKind = ErrorKind::IsA;
273  i.split_at_position1_complete(|c| !arr.find_token(c), e)
274    .into_output()
275}
276
277/// Returns the longest input slice (if any) that matches the predicate.
278///
279/// The parser will return the longest slice that matches the given predicate *(a function that
280/// takes the input and returns a bool)*.
281/// # Example
282/// ```rust
283/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
284/// use nom8::bytes::complete::take_while;
285/// use nom8::input::AsChar;
286///
287/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
288///   take_while(AsChar::is_alpha)(s)
289/// }
290///
291/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
292/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
293/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
294/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
295/// ```
296///
297/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while`][crate::bytes::take_while]
298#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while`")]
299pub fn take_while<T, Input, Error: ParseError<Input>>(
300  list: T,
301) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
302where
303  Input: InputTakeAtPosition,
304  Input: IntoOutput,
305  T: FindToken<<Input as InputTakeAtPosition>::Item>,
306{
307  move |i: Input| take_while_internal(i, &list)
308}
309
310pub(crate) fn take_while_internal<T, Input, Error: ParseError<Input>>(
311  i: Input,
312  list: &T,
313) -> IResult<Input, <Input as IntoOutput>::Output, Error>
314where
315  Input: InputTakeAtPosition,
316  Input: IntoOutput,
317  T: FindToken<<Input as InputTakeAtPosition>::Item>,
318{
319  i.split_at_position_complete(|c| !list.find_token(c))
320    .into_output()
321}
322
323/// Returns the longest (at least 1) input slice that matches the predicate.
324///
325/// The parser will return the longest slice that matches the given predicate *(a function that
326/// takes the input and returns a bool)*.
327///
328/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
329/// # Example
330/// ```rust
331/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
332/// use nom8::bytes::complete::take_while1;
333/// use nom8::input::AsChar;
334///
335/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
336///   take_while1(AsChar::is_alpha)(s)
337/// }
338///
339/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
340/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
341/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
342/// ```
343///
344/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1]
345#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while1`")]
346pub fn take_while1<T, Input, Error: ParseError<Input>>(
347  list: T,
348) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
349where
350  Input: InputTakeAtPosition,
351  Input: IntoOutput,
352  T: FindToken<<Input as InputTakeAtPosition>::Item>,
353{
354  move |i: Input| take_while1_internal(i, &list)
355}
356
357pub(crate) fn take_while1_internal<T, Input, Error: ParseError<Input>>(
358  i: Input,
359  list: &T,
360) -> IResult<Input, <Input as IntoOutput>::Output, Error>
361where
362  Input: InputTakeAtPosition,
363  Input: IntoOutput,
364  T: FindToken<<Input as InputTakeAtPosition>::Item>,
365{
366  let e: ErrorKind = ErrorKind::TakeWhile1;
367  i.split_at_position1_complete(|c| !list.find_token(c), e)
368    .into_output()
369}
370
371/// Returns the longest (m <= len <= n) input slice  that matches the predicate.
372///
373/// The parser will return the longest slice that matches the given predicate *(a function that
374/// takes the input and returns a bool)*.
375///
376/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out
377/// of range (m <= len <= n).
378/// # Example
379/// ```rust
380/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
381/// use nom8::bytes::complete::take_while_m_n;
382/// use nom8::input::AsChar;
383///
384/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
385///   take_while_m_n(3, 6, AsChar::is_alpha)(s)
386/// }
387///
388/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
389/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
390/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
391/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN))));
392/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
393/// ```
394///
395/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while_m_n`][crate::bytes::take_while_m_n]
396#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while_m_n`")]
397pub fn take_while_m_n<T, Input, Error: ParseError<Input>>(
398  m: usize,
399  n: usize,
400  list: T,
401) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
402where
403  Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
404  Input: IntoOutput,
405  T: FindToken<<Input as InputIter>::Item>,
406{
407  move |i: Input| take_while_m_n_internal(i, m, n, &list)
408}
409
410pub(crate) fn take_while_m_n_internal<T, Input, Error: ParseError<Input>>(
411  input: Input,
412  m: usize,
413  n: usize,
414  list: &T,
415) -> IResult<Input, <Input as IntoOutput>::Output, Error>
416where
417  Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
418  Input: IntoOutput,
419  T: FindToken<<Input as InputIter>::Item>,
420{
421  match input.position(|c| !list.find_token(c)) {
422    Some(idx) => {
423      if idx >= m {
424        if idx <= n {
425          let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) {
426            Ok(input.take_split(index)).into_output()
427          } else {
428            Err(Err::Error(Error::from_error_kind(
429              input,
430              ErrorKind::TakeWhileMN,
431            )))
432          };
433          res
434        } else {
435          let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) {
436            Ok(input.take_split(index)).into_output()
437          } else {
438            Err(Err::Error(Error::from_error_kind(
439              input,
440              ErrorKind::TakeWhileMN,
441            )))
442          };
443          res
444        }
445      } else {
446        let e = ErrorKind::TakeWhileMN;
447        Err(Err::Error(Error::from_error_kind(input, e)))
448      }
449    }
450    None => {
451      let len = input.input_len();
452      if len >= n {
453        match input.slice_index(n) {
454          Ok(index) => Ok(input.take_split(index)).into_output(),
455          Err(_needed) => Err(Err::Error(Error::from_error_kind(
456            input,
457            ErrorKind::TakeWhileMN,
458          ))),
459        }
460      } else if len >= m && len <= n {
461        let res: IResult<_, _, Error> = Ok((input.slice(len..), input));
462        res.into_output()
463      } else {
464        let e = ErrorKind::TakeWhileMN;
465        Err(Err::Error(Error::from_error_kind(input, e)))
466      }
467    }
468  }
469}
470
471/// Returns the longest input slice (if any) till a predicate is met.
472///
473/// The parser will return the longest slice till the given predicate *(a function that
474/// takes the input and returns a bool)*.
475/// # Example
476/// ```rust
477/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
478/// use nom8::bytes::complete::take_till;
479///
480/// fn till_colon(s: &str) -> IResult<&str, &str> {
481///   take_till(|c| c == ':')(s)
482/// }
483///
484/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
485/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
486/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
487/// assert_eq!(till_colon(""), Ok(("", "")));
488/// ```
489///
490/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till`][crate::bytes::take_till]
491#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till`")]
492pub fn take_till<T, Input, Error: ParseError<Input>>(
493  list: T,
494) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
495where
496  Input: InputTakeAtPosition,
497  Input: IntoOutput,
498  T: FindToken<<Input as InputTakeAtPosition>::Item>,
499{
500  move |i: Input| take_till_internal(i, &list)
501}
502
503pub(crate) fn take_till_internal<T, Input, Error: ParseError<Input>>(
504  i: Input,
505  list: &T,
506) -> IResult<Input, <Input as IntoOutput>::Output, Error>
507where
508  Input: InputTakeAtPosition,
509  Input: IntoOutput,
510  T: FindToken<<Input as InputTakeAtPosition>::Item>,
511{
512  i.split_at_position_complete(|c| list.find_token(c))
513    .into_output()
514}
515
516/// Returns the longest (at least 1) input slice till a predicate is met.
517///
518/// The parser will return the longest slice till the given predicate *(a function that
519/// takes the input and returns a bool)*.
520///
521/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the
522/// predicate matches the first input.
523/// # Example
524/// ```rust
525/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
526/// use nom8::bytes::complete::take_till1;
527///
528/// fn till_colon(s: &str) -> IResult<&str, &str> {
529///   take_till1(|c| c == ':')(s)
530/// }
531///
532/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
533/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
534/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
535/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
536/// ```
537///
538/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1]
539#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till1`")]
540pub fn take_till1<T, Input, Error: ParseError<Input>>(
541  list: T,
542) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
543where
544  Input: InputTakeAtPosition,
545  Input: IntoOutput,
546  T: FindToken<<Input as InputTakeAtPosition>::Item>,
547{
548  move |i: Input| take_till1_internal(i, &list)
549}
550
551pub(crate) fn take_till1_internal<T, Input, Error: ParseError<Input>>(
552  i: Input,
553  list: &T,
554) -> IResult<Input, <Input as IntoOutput>::Output, Error>
555where
556  Input: InputTakeAtPosition,
557  Input: IntoOutput,
558  T: FindToken<<Input as InputTakeAtPosition>::Item>,
559{
560  let e: ErrorKind = ErrorKind::TakeTill1;
561  i.split_at_position1_complete(|c| list.find_token(c), e)
562    .into_output()
563}
564
565/// Returns an input slice containing the first N input elements (Input[..N]).
566///
567/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument.
568/// # Example
569/// ```rust
570/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
571/// use nom8::bytes::complete::take;
572///
573/// fn take6(s: &str) -> IResult<&str, &str> {
574///   take(6usize)(s)
575/// }
576///
577/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
578/// assert_eq!(take6("things"), Ok(("", "things")));
579/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
580/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
581/// ```
582///
583/// The units that are taken will depend on the input type. For example, for a
584/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
585/// take that many `u8`'s:
586///
587/// ```rust
588/// use nom8::error::Error;
589/// use nom8::bytes::complete::take;
590///
591/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙")));
592/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
593/// ```
594///
595/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take`][crate::bytes::take]
596#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take`")]
597pub fn take<C, Input, Error: ParseError<Input>>(
598  count: C,
599) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
600where
601  Input: InputIter + InputTake,
602  Input: IntoOutput,
603  C: ToUsize,
604{
605  let c = count.to_usize();
606  move |i: Input| take_internal(i, c)
607}
608
609pub(crate) fn take_internal<Input, Error: ParseError<Input>>(
610  i: Input,
611  c: usize,
612) -> IResult<Input, <Input as IntoOutput>::Output, Error>
613where
614  Input: InputIter + InputTake,
615  Input: IntoOutput,
616{
617  match i.slice_index(c) {
618    Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))),
619    Ok(index) => Ok(i.take_split(index)).into_output(),
620  }
621}
622
623/// Returns the input slice up to the first occurrence of the pattern.
624///
625/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
626/// if the pattern wasn't met.
627/// # Example
628/// ```rust
629/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
630/// use nom8::bytes::complete::take_until;
631///
632/// fn until_eof(s: &str) -> IResult<&str, &str> {
633///   take_until("eof")(s)
634/// }
635///
636/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
637/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
638/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
639/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
640/// ```
641///
642/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until`][crate::bytes::take_until]
643#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_until`")]
644pub fn take_until<T, Input, Error: ParseError<Input>>(
645  tag: T,
646) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
647where
648  Input: InputTake + FindSubstring<T>,
649  Input: IntoOutput,
650  T: InputLength + Clone,
651{
652  move |i: Input| take_until_internal(i, tag.clone())
653}
654
655pub(crate) fn take_until_internal<T, Input, Error: ParseError<Input>>(
656  i: Input,
657  t: T,
658) -> IResult<Input, <Input as IntoOutput>::Output, Error>
659where
660  Input: InputTake + FindSubstring<T>,
661  Input: IntoOutput,
662  T: InputLength,
663{
664  let res: IResult<_, _, Error> = match i.find_substring(t) {
665    None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
666    Some(index) => Ok(i.take_split(index)),
667  };
668  res.into_output()
669}
670
671/// Returns the non empty input slice up to the first occurrence of the pattern.
672///
673/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
674/// if the pattern wasn't met.
675/// # Example
676/// ```rust
677/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
678/// use nom8::bytes::complete::take_until1;
679///
680/// fn until_eof(s: &str) -> IResult<&str, &str> {
681///   take_until1("eof")(s)
682/// }
683///
684/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
685/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
686/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
687/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
688/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
689/// ```
690///
691/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until1`][crate::bytes::take_until1]
692#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_until1`")]
693pub fn take_until1<T, Input, Error: ParseError<Input>>(
694  tag: T,
695) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
696where
697  Input: InputTake + FindSubstring<T>,
698  Input: IntoOutput,
699  T: InputLength + Clone,
700{
701  move |i: Input| take_until1_internal(i, tag.clone())
702}
703
704pub(crate) fn take_until1_internal<T, Input, Error: ParseError<Input>>(
705  i: Input,
706  t: T,
707) -> IResult<Input, <Input as IntoOutput>::Output, Error>
708where
709  Input: InputTake + FindSubstring<T>,
710  Input: IntoOutput,
711  T: InputLength,
712{
713  let res: IResult<_, _, Error> = match i.find_substring(t) {
714    None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
715    Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
716    Some(index) => Ok(i.take_split(index)),
717  };
718  res.into_output()
719}
720
721/// Matches a byte string with escaped characters.
722///
723/// * The first argument matches the normal characters (it must not accept the control character)
724/// * The second argument is the control character (like `\` in most languages)
725/// * The third argument matches the escaped characters
726/// # Example
727/// ```
728/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
729/// # use nom8::character::complete::digit1;
730/// use nom8::bytes::complete::escaped;
731/// use nom8::character::complete::one_of;
732///
733/// fn esc(s: &str) -> IResult<&str, &str> {
734///   escaped(digit1, '\\', one_of(r#""n\"#))(s)
735/// }
736///
737/// assert_eq!(esc("123;"), Ok((";", "123")));
738/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#)));
739/// ```
740///
741///
742/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped`][crate::bytes::escaped]
743#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::escaped`")]
744pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>(
745  mut normal: F,
746  control_char: char,
747  mut escapable: G,
748) -> impl FnMut(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
749where
750  Input: Clone
751    + crate::input::Offset
752    + InputLength
753    + InputTake
754    + InputTakeAtPosition
755    + Slice<RangeFrom<usize>>
756    + InputIter,
757  Input: IntoOutput,
758  <Input as InputIter>::Item: crate::input::AsChar,
759  F: Parser<Input, O1, Error>,
760  G: Parser<Input, O2, Error>,
761  Error: ParseError<Input>,
762{
763  move |input: Input| escaped_internal(input, &mut normal, control_char, &mut escapable)
764}
765
766pub(crate) fn escaped_internal<'a, Input: 'a, Error, F, G, O1, O2>(
767  input: Input,
768  normal: &mut F,
769  control_char: char,
770  escapable: &mut G,
771) -> IResult<Input, <Input as IntoOutput>::Output, Error>
772where
773  Input: Clone
774    + crate::input::Offset
775    + InputLength
776    + InputTake
777    + InputTakeAtPosition
778    + Slice<RangeFrom<usize>>
779    + InputIter,
780  Input: IntoOutput,
781  <Input as InputIter>::Item: crate::input::AsChar,
782  F: Parser<Input, O1, Error>,
783  G: Parser<Input, O2, Error>,
784  Error: ParseError<Input>,
785{
786  use crate::input::AsChar;
787
788  let mut i = input.clone();
789
790  while i.input_len() > 0 {
791    let current_len = i.input_len();
792
793    match normal.parse(i.clone()) {
794      Ok((i2, _)) => {
795        // return if we consumed everything or if the normal parser
796        // does not consume anything
797        if i2.input_len() == 0 {
798          return Ok((input.slice(input.input_len()..), input)).into_output();
799        } else if i2.input_len() == current_len {
800          let index = input.offset(&i2);
801          return Ok(input.take_split(index)).into_output();
802        } else {
803          i = i2;
804        }
805      }
806      Err(Err::Error(_)) => {
807        // unwrap() should be safe here since index < $i.input_len()
808        if i.iter_elements().next().unwrap().as_char() == control_char {
809          let next = control_char.len_utf8();
810          if next >= i.input_len() {
811            return Err(Err::Error(Error::from_error_kind(
812              input,
813              ErrorKind::Escaped,
814            )));
815          } else {
816            match escapable.parse(i.slice(next..)) {
817              Ok((i2, _)) => {
818                if i2.input_len() == 0 {
819                  return Ok((input.slice(input.input_len()..), input)).into_output();
820                } else {
821                  i = i2;
822                }
823              }
824              Err(e) => return Err(e),
825            }
826          }
827        } else {
828          let index = input.offset(&i);
829          if index == 0 {
830            return Err(Err::Error(Error::from_error_kind(
831              input,
832              ErrorKind::Escaped,
833            )));
834          }
835          return Ok(input.take_split(index)).into_output();
836        }
837      }
838      Err(e) => {
839        return Err(e);
840      }
841    }
842  }
843
844  Ok((input.slice(input.input_len()..), input)).into_output()
845}
846
847/// Matches a byte string with escaped characters.
848///
849/// * The first argument matches the normal characters (it must not match the control character)
850/// * The second argument is the control character (like `\` in most languages)
851/// * The third argument matches the escaped characters and transforms them
852///
853/// As an example, the chain `abc\tdef` could be `abc    def` (it also consumes the control character)
854///
855/// ```
856/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
857/// # use std::str::from_utf8;
858/// use nom8::bytes::complete::{escaped_transform, tag};
859/// use nom8::character::complete::alpha1;
860/// use nom8::branch::alt;
861/// use nom8::combinator::value;
862///
863/// fn parser(input: &str) -> IResult<&str, String> {
864///   escaped_transform(
865///     alpha1,
866///     '\\',
867///     alt((
868///       value("\\", tag("\\")),
869///       value("\"", tag("\"")),
870///       value("\n", tag("n")),
871///     ))
872///   )(input)
873/// }
874///
875/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd"))));
876/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd"))));
877/// ```
878#[cfg(feature = "alloc")]
879///
880/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped_transform`][crate::bytes::escaped_transform]
881#[deprecated(
882  since = "8.0.0",
883  note = "Replaced with `nom8::bytes::escaped_transform`"
884)]
885pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
886  mut normal: F,
887  control_char: char,
888  mut transform: G,
889) -> impl FnMut(Input) -> IResult<Input, Output, Error>
890where
891  Input: Clone
892    + crate::input::Offset
893    + InputLength
894    + InputTake
895    + InputTakeAtPosition
896    + Slice<RangeFrom<usize>>
897    + InputIter,
898  Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
899  O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
900  O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
901  <Input as InputIter>::Item: crate::input::AsChar,
902  F: Parser<Input, O1, Error>,
903  G: Parser<Input, O2, Error>,
904  Error: ParseError<Input>,
905{
906  move |input: Input| escaped_transform_internal(input, &mut normal, control_char, &mut transform)
907}
908
909#[cfg(feature = "alloc")]
910pub(crate) fn escaped_transform_internal<Input, Error, F, G, O1, O2, ExtendItem, Output>(
911  input: Input,
912  normal: &mut F,
913  control_char: char,
914  transform: &mut G,
915) -> IResult<Input, Output, Error>
916where
917  Input: Clone
918    + crate::input::Offset
919    + InputLength
920    + InputTake
921    + InputTakeAtPosition
922    + Slice<RangeFrom<usize>>
923    + InputIter,
924  Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
925  O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
926  O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
927  <Input as InputIter>::Item: crate::input::AsChar,
928  F: Parser<Input, O1, Error>,
929  G: Parser<Input, O2, Error>,
930  Error: ParseError<Input>,
931{
932  use crate::input::AsChar;
933
934  let mut index = 0;
935  let mut res = input.new_builder();
936
937  let i = input.clone();
938
939  while index < i.input_len() {
940    let current_len = i.input_len();
941    let remainder = i.slice(index..);
942    match normal.parse(remainder.clone()) {
943      Ok((i2, o)) => {
944        o.extend_into(&mut res);
945        if i2.input_len() == 0 {
946          return Ok((i.slice(i.input_len()..), res));
947        } else if i2.input_len() == current_len {
948          return Ok((remainder, res));
949        } else {
950          index = input.offset(&i2);
951        }
952      }
953      Err(Err::Error(_)) => {
954        // unwrap() should be safe here since index < $i.input_len()
955        if remainder.iter_elements().next().unwrap().as_char() == control_char {
956          let next = index + control_char.len_utf8();
957          let input_len = input.input_len();
958
959          if next >= input_len {
960            return Err(Err::Error(Error::from_error_kind(
961              remainder,
962              ErrorKind::EscapedTransform,
963            )));
964          } else {
965            match transform.parse(i.slice(next..)) {
966              Ok((i2, o)) => {
967                o.extend_into(&mut res);
968                if i2.input_len() == 0 {
969                  return Ok((i.slice(i.input_len()..), res));
970                } else {
971                  index = input.offset(&i2);
972                }
973              }
974              Err(e) => return Err(e),
975            }
976          }
977        } else {
978          if index == 0 {
979            return Err(Err::Error(Error::from_error_kind(
980              remainder,
981              ErrorKind::EscapedTransform,
982            )));
983          }
984          return Ok((remainder, res));
985        }
986      }
987      Err(e) => return Err(e),
988    }
989  }
990  Ok((input.slice(index..), res))
991}
992
993#[cfg(test)]
994mod tests {
995  use super::*;
996  use crate::character::complete::{alpha1 as alpha, digit1 as digit};
997  #[cfg(feature = "alloc")]
998  use crate::{
999    branch::alt,
1000    combinator::{map, value},
1001    lib::std::string::String,
1002    lib::std::vec::Vec,
1003  };
1004
1005  #[test]
1006  fn complete_take_while_m_n_utf8_all_matching() {
1007    let result: IResult<&str, &str> =
1008      super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn");
1009    assert_eq!(result, Ok(("", "øn")));
1010  }
1011
1012  #[test]
1013  fn complete_take_while_m_n_utf8_all_matching_substring() {
1014    let result: IResult<&str, &str> =
1015      super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn");
1016    assert_eq!(result, Ok(("n", "ø")));
1017  }
1018
1019  // issue #1336 "escaped hangs if normal parser accepts empty"
1020  fn escaped_string(input: &str) -> IResult<&str, &str> {
1021    use crate::character::complete::{alpha0, one_of};
1022    escaped(alpha0, '\\', one_of("n"))(input)
1023  }
1024
1025  // issue #1336 "escaped hangs if normal parser accepts empty"
1026  #[test]
1027  fn escaped_hang() {
1028    escaped_string("7").unwrap();
1029    escaped_string("a7").unwrap();
1030  }
1031
1032  // issue ##1118 escaped does not work with empty string
1033  fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> {
1034    use crate::bytes::complete::*;
1035    use crate::character::complete::*;
1036    use crate::combinator::opt;
1037    use crate::sequence::delimited;
1038
1039    delimited(
1040      char('"'),
1041      escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
1042      char('"'),
1043    )(input)
1044  }
1045
1046  #[test]
1047  fn escaped_hang_1118() {
1048    assert_eq!(unquote(r#""""#), Ok(("", "")));
1049  }
1050
1051  #[cfg(feature = "alloc")]
1052  #[allow(unused_variables)]
1053  #[test]
1054  fn escaping() {
1055    use crate::character::complete::one_of;
1056
1057    fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> {
1058      escaped(alpha, '\\', one_of("\"n\\"))(i)
1059    }
1060    assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
1061    assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
1062    assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
1063    assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
1064    assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
1065    assert_eq!(
1066      esc(&b"AB\\"[..]),
1067      Err(Err::Error(error_position!(
1068        &b"AB\\"[..],
1069        ErrorKind::Escaped
1070      )))
1071    );
1072    assert_eq!(
1073      esc(&b"AB\\A"[..]),
1074      Err(Err::Error(error_node_position!(
1075        &b"AB\\A"[..],
1076        ErrorKind::Escaped,
1077        error_position!(&b"A"[..], ErrorKind::OneOf)
1078      )))
1079    );
1080
1081    fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> {
1082      escaped(digit, '\\', one_of("\"n\\"))(i)
1083    }
1084    assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
1085  }
1086
1087  #[cfg(feature = "alloc")]
1088  #[test]
1089  fn escaping_str() {
1090    use crate::character::complete::one_of;
1091
1092    fn esc(i: &str) -> IResult<&str, &str> {
1093      escaped(alpha, '\\', one_of("\"n\\"))(i)
1094    }
1095    assert_eq!(esc("abcd;"), Ok((";", "abcd")));
1096    assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
1097    assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
1098    assert_eq!(esc("\\n;"), Ok((";", "\\n")));
1099    assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
1100    assert_eq!(
1101      esc("AB\\"),
1102      Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped)))
1103    );
1104    assert_eq!(
1105      esc("AB\\A"),
1106      Err(Err::Error(error_node_position!(
1107        "AB\\A",
1108        ErrorKind::Escaped,
1109        error_position!("A", ErrorKind::OneOf)
1110      )))
1111    );
1112
1113    fn esc2(i: &str) -> IResult<&str, &str> {
1114      escaped(digit, '\\', one_of("\"n\\"))(i)
1115    }
1116    assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));
1117
1118    fn esc3(i: &str) -> IResult<&str, &str> {
1119      escaped(alpha, '\u{241b}', one_of("\"n"))(i)
1120    }
1121    assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
1122  }
1123
1124  #[cfg(feature = "alloc")]
1125  fn to_s(i: Vec<u8>) -> String {
1126    String::from_utf8_lossy(&i).into_owned()
1127  }
1128
1129  #[cfg(feature = "alloc")]
1130  #[test]
1131  fn escape_transform() {
1132    fn esc(i: &[u8]) -> IResult<&[u8], String> {
1133      map(
1134        escaped_transform(
1135          alpha,
1136          '\\',
1137          alt((
1138            value(&b"\\"[..], tag("\\")),
1139            value(&b"\""[..], tag("\"")),
1140            value(&b"\n"[..], tag("n")),
1141          )),
1142        ),
1143        to_s,
1144      )(i)
1145    }
1146
1147    assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
1148    assert_eq!(
1149      esc(&b"ab\\\"cd;"[..]),
1150      Ok((&b";"[..], String::from("ab\"cd")))
1151    );
1152    assert_eq!(
1153      esc(&b"\\\"abcd;"[..]),
1154      Ok((&b";"[..], String::from("\"abcd")))
1155    );
1156    assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
1157    assert_eq!(
1158      esc(&b"ab\\\"12"[..]),
1159      Ok((&b"12"[..], String::from("ab\"")))
1160    );
1161    assert_eq!(
1162      esc(&b"AB\\"[..]),
1163      Err(Err::Error(error_position!(
1164        &b"\\"[..],
1165        ErrorKind::EscapedTransform
1166      )))
1167    );
1168    assert_eq!(
1169      esc(&b"AB\\A"[..]),
1170      Err(Err::Error(error_node_position!(
1171        &b"AB\\A"[..],
1172        ErrorKind::EscapedTransform,
1173        error_position!(&b"A"[..], ErrorKind::Tag)
1174      )))
1175    );
1176
1177    fn esc2(i: &[u8]) -> IResult<&[u8], String> {
1178      map(
1179        escaped_transform(
1180          alpha,
1181          '&',
1182          alt((
1183            value("è".as_bytes(), tag("egrave;")),
1184            value("Ă ".as_bytes(), tag("agrave;")),
1185          )),
1186        ),
1187        to_s,
1188      )(i)
1189    }
1190    assert_eq!(
1191      esc2(&b"ab&egrave;DEF;"[..]),
1192      Ok((&b";"[..], String::from("abèDEF")))
1193    );
1194    assert_eq!(
1195      esc2(&b"ab&egrave;D&agrave;EF;"[..]),
1196      Ok((&b";"[..], String::from("abèDàEF")))
1197    );
1198  }
1199
1200  #[cfg(feature = "std")]
1201  #[test]
1202  fn escape_transform_str() {
1203    fn esc(i: &str) -> IResult<&str, String> {
1204      escaped_transform(
1205        alpha,
1206        '\\',
1207        alt((
1208          value("\\", tag("\\")),
1209          value("\"", tag("\"")),
1210          value("\n", tag("n")),
1211        )),
1212      )(i)
1213    }
1214
1215    assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
1216    assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
1217    assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
1218    assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
1219    assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
1220    assert_eq!(
1221      esc("AB\\"),
1222      Err(Err::Error(error_position!(
1223        "\\",
1224        ErrorKind::EscapedTransform
1225      )))
1226    );
1227    assert_eq!(
1228      esc("AB\\A"),
1229      Err(Err::Error(error_node_position!(
1230        "AB\\A",
1231        ErrorKind::EscapedTransform,
1232        error_position!("A", ErrorKind::Tag)
1233      )))
1234    );
1235
1236    fn esc2(i: &str) -> IResult<&str, String> {
1237      escaped_transform(
1238        alpha,
1239        '&',
1240        alt((value("è", tag("egrave;")), value("à", tag("agrave;")))),
1241      )(i)
1242    }
1243    assert_eq!(esc2("ab&egrave;DEF;"), Ok((";", String::from("abèDEF"))));
1244    assert_eq!(
1245      esc2("ab&egrave;D&agrave;EF;"),
1246      Ok((";", String::from("abèDàEF")))
1247    );
1248
1249    fn esc3(i: &str) -> IResult<&str, String> {
1250      escaped_transform(
1251        alpha,
1252        '␛',
1253        alt((value("\0", tag("0")), value("\n", tag("n")))),
1254      )(i)
1255    }
1256    assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
1257  }
1258}