nom8/character/
streaming.rs

1//! Character specific parsers and combinators, streaming version
2//!
3//! Functions recognizing specific characters
4
5#![allow(deprecated)]
6
7use crate::branch::alt;
8use crate::combinator::opt;
9use crate::error::ErrorKind;
10use crate::error::ParseError;
11use crate::input::{
12  AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, IntoOutput, Slice,
13};
14use crate::input::{Compare, CompareResult};
15use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
16use crate::IntoOutputIResult as _;
17use crate::{Err, IResult, Needed};
18
19/// Recognizes one character.
20///
21/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
22/// # Example
23///
24/// ```
25/// # use nom8::{Err, error::{ErrorKind, Error}, Needed, IResult};
26/// # use nom8::character::streaming::char;
27/// fn parser(i: &str) -> IResult<&str, char> {
28///     char('a')(i)
29/// }
30/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
31/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char))));
32/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1))));
33/// ```
34///
35/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
36#[deprecated(
37  since = "8.0.0",
38  note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
39)]
40pub fn char<I, Error: ParseError<I>>(c: char) -> impl Fn(I) -> IResult<I, char, Error>
41where
42  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
43  <I as InputIter>::Item: AsChar,
44{
45  move |i: I| char_internal(i, c)
46}
47
48pub(crate) fn char_internal<I, Error: ParseError<I>>(i: I, c: char) -> IResult<I, char, Error>
49where
50  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
51  <I as InputIter>::Item: AsChar,
52{
53  match (i).iter_elements().next().map(|t| {
54    let b = t.as_char() == c;
55    (&c, b)
56  }) {
57    None => Err(Err::Incomplete(Needed::new(c.len() - i.input_len()))),
58    Some((_, false)) => Err(Err::Error(Error::from_char(i, c))),
59    Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())),
60  }
61}
62
63/// Recognizes one character and checks that it satisfies a predicate
64///
65/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
66/// # Example
67///
68/// ```
69/// # use nom8::{Err, error::{ErrorKind, Error}, Needed, IResult};
70/// # use nom8::character::streaming::satisfy;
71/// fn parser(i: &str) -> IResult<&str, char> {
72///     satisfy(|c| c == 'a' || c == 'b')(i)
73/// }
74/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
75/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy))));
76/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Unknown)));
77/// ```
78///
79/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
80#[deprecated(
81  since = "8.0.0",
82  note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
83)]
84pub fn satisfy<F, I, Error: ParseError<I>>(cond: F) -> impl Fn(I) -> IResult<I, char, Error>
85where
86  I: Slice<RangeFrom<usize>> + InputIter,
87  <I as InputIter>::Item: AsChar,
88  F: Fn(char) -> bool,
89{
90  move |i: I| satisfy_internal(i, &cond)
91}
92
93pub(crate) fn satisfy_internal<F, I, Error: ParseError<I>>(
94  i: I,
95  cond: &F,
96) -> IResult<I, char, Error>
97where
98  I: Slice<RangeFrom<usize>> + InputIter,
99  <I as InputIter>::Item: AsChar,
100  F: Fn(char) -> bool,
101{
102  match (i).iter_elements().next().map(|t| {
103    let c = t.as_char();
104    let b = cond(c);
105    (c, b)
106  }) {
107    None => Err(Err::Incomplete(Needed::Unknown)),
108    Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))),
109    Some((c, true)) => Ok((i.slice(c.len()..), c)),
110  }
111}
112
113/// Recognizes one of the provided characters.
114///
115/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
116/// # Example
117///
118/// ```
119/// # use nom8::{Err, error::ErrorKind, Needed};
120/// # use nom8::character::streaming::one_of;
121/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("abc")("b"), Ok(("", 'b')));
122/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf))));
123/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1))));
124/// ```
125///
126/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
127#[deprecated(
128  since = "8.0.0",
129  note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
130)]
131pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
132where
133  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
134  <I as InputIter>::Item: AsChar + Copy,
135  T: FindToken<<I as InputIter>::Item>,
136{
137  move |i: I| crate::bytes::streaming::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
138}
139
140/// Recognizes a character that is not in the provided characters.
141///
142/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
143/// # Example
144///
145/// ```
146/// # use nom8::{Err, error::ErrorKind, Needed};
147/// # use nom8::character::streaming::none_of;
148/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z')));
149/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf))));
150/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1))));
151/// ```
152///
153/// **WARNING:** Deprecated, replaced with [`nom8::bytes::none_of`][crate::bytes::none_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
154#[deprecated(
155  since = "8.0.0",
156  note = "Replaced with `nom8::bytes::none_of` with input wrapped in `nom8::input::Streaming`"
157)]
158pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
159where
160  I: Slice<RangeFrom<usize>> + InputLength + InputIter,
161  <I as InputIter>::Item: AsChar + Copy,
162  T: FindToken<<I as InputIter>::Item>,
163{
164  move |i: I| crate::bytes::streaming::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
165}
166
167/// Recognizes the string "\r\n".
168///
169/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
170/// # Example
171///
172/// ```
173/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
174/// # use nom8::character::streaming::crlf;
175/// assert_eq!(crlf::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n")));
176/// assert_eq!(crlf::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf))));
177/// assert_eq!(crlf::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(2))));
178/// ```
179///
180/// **WARNING:** Deprecated, replaced with [`nom8::character::crlf`][crate::character::crlf] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
181#[deprecated(
182  since = "8.0.0",
183  note = "Replaced with `nom8::character::crlf` with input wrapped in `nom8::input::Streaming`"
184)]
185pub fn crlf<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
186where
187  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
188  T: InputIter,
189  T: IntoOutput,
190  T: Compare<&'static str>,
191{
192  match input.compare("\r\n") {
193    //FIXME: is this the right index?
194    CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
195    CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))),
196    CompareResult::Error => {
197      let e: ErrorKind = ErrorKind::CrLf;
198      Err(Err::Error(E::from_error_kind(input, e)))
199    }
200  }
201}
202
203/// Recognizes a string of any char except '\r\n' or '\n'.
204///
205/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
206/// # Example
207///
208/// ```
209/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
210/// # use nom8::character::streaming::not_line_ending;
211/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Ok(("\r\nc", "ab")));
212/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("abc"), Err(Err::Incomplete(Needed::Unknown)));
213/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::Unknown)));
214/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rb\nc"), Err(Err::Error(("a\rb\nc", ErrorKind::Tag ))));
215/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rbc"), Err(Err::Error(("a\rbc", ErrorKind::Tag ))));
216/// ```
217///
218/// **WARNING:** Deprecated, replaced with [`nom8::character::not_line_ending`][crate::character::not_line_ending] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
219#[deprecated(
220  since = "8.0.0",
221  note = "Replaced with `nom8::character::not_line_ending` with input wrapped in `nom8::input::Streaming`"
222)]
223pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
224where
225  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
226  T: InputIter + InputLength,
227  T: IntoOutput,
228  T: Compare<&'static str>,
229  <T as InputIter>::Item: AsChar,
230  <T as InputIter>::Item: AsChar,
231{
232  match input.position(|item| {
233    let c = item.as_char();
234    c == '\r' || c == '\n'
235  }) {
236    None => Err(Err::Incomplete(Needed::Unknown)),
237    Some(index) => {
238      let mut it = input.slice(index..).iter_elements();
239      let nth = it.next().unwrap().as_char();
240      if nth == '\r' {
241        let sliced = input.slice(index..);
242        let comp = sliced.compare("\r\n");
243        match comp {
244          //FIXME: calculate the right index
245          CompareResult::Incomplete => Err(Err::Incomplete(Needed::Unknown)),
246          CompareResult::Error => {
247            let e: ErrorKind = ErrorKind::Tag;
248            Err(Err::Error(E::from_error_kind(input, e)))
249          }
250          CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))).into_output(),
251        }
252      } else {
253        Ok((input.slice(index..), input.slice(..index))).into_output()
254      }
255    }
256  }
257}
258
259/// Recognizes an end of line (both '\n' and '\r\n').
260///
261/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
262/// # Example
263///
264/// ```
265/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
266/// # use nom8::character::streaming::line_ending;
267/// assert_eq!(line_ending::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n")));
268/// assert_eq!(line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf))));
269/// assert_eq!(line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
270/// ```
271///
272/// **WARNING:** Deprecated, replaced with [`nom8::character::line_ending`][crate::character::line_ending] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
273#[deprecated(
274  since = "8.0.0",
275  note = "Replaced with `nom8::character::line_ending` with input wrapped in `nom8::input::Streaming`"
276)]
277pub fn line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
278where
279  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
280  T: InputIter + InputLength,
281  T: IntoOutput,
282  T: Compare<&'static str>,
283{
284  match input.compare("\n") {
285    CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))).into_output(),
286    CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(1))),
287    CompareResult::Error => {
288      match input.compare("\r\n") {
289        //FIXME: is this the right index?
290        CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
291        CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))),
292        CompareResult::Error => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))),
293      }
294    }
295  }
296}
297
298/// Matches a newline character '\\n'.
299///
300/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
301/// # Example
302///
303/// ```
304/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
305/// # use nom8::character::streaming::newline;
306/// assert_eq!(newline::<_, (_, ErrorKind)>("\nc"), Ok(("c", '\n')));
307/// assert_eq!(newline::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char))));
308/// assert_eq!(newline::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
309/// ```
310///
311/// **WARNING:** Deprecated, replaced with [`nom8::character::newline`][crate::character::newline] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
312#[deprecated(
313  since = "8.0.0",
314  note = "Replaced with `nom8::character::newline` with input wrapped in `nom8::input::Streaming`"
315)]
316pub fn newline<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
317where
318  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
319  <I as InputIter>::Item: AsChar,
320{
321  char('\n')(input)
322}
323
324/// Matches a tab character '\t'.
325///
326/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
327/// # Example
328///
329/// ```
330/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
331/// # use nom8::character::streaming::tab;
332/// assert_eq!(tab::<_, (_, ErrorKind)>("\tc"), Ok(("c", '\t')));
333/// assert_eq!(tab::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char))));
334/// assert_eq!(tab::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
335/// ```
336///
337/// **WARNING:** Deprecated, replaced with [`nom8::character::tab`][crate::character::tab] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
338#[deprecated(
339  since = "8.0.0",
340  note = "Replaced with `nom8::character::tab` with input wrapped in `nom8::input::Streaming`"
341)]
342pub fn tab<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
343where
344  I: Slice<RangeFrom<usize>> + InputIter + InputLength,
345  <I as InputIter>::Item: AsChar,
346{
347  char('\t')(input)
348}
349
350/// Matches one byte as a character. Note that the input type will
351/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
352///
353/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
354/// # Example
355///
356/// ```
357/// # use nom8::{character::streaming::anychar, Err, error::ErrorKind, IResult, Needed};
358/// assert_eq!(anychar::<_, (_, ErrorKind)>("abc"), Ok(("bc",'a')));
359/// assert_eq!(anychar::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
360/// ```
361///
362/// **WARNING:** Deprecated, replaced with [`nom8::bytes::any`][crate::bytes::any] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
363#[deprecated(
364  since = "8.0.0",
365  note = "Replaced with `nom8::bytes::any` with input wrapped in `nom8::input::Streaming`"
366)]
367pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E>
368where
369  T: InputIter + InputLength + Slice<RangeFrom<usize>>,
370  <T as InputIter>::Item: AsChar,
371{
372  crate::bytes::streaming::any(input).map(|(i, c)| (i, c.as_char()))
373}
374
375/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
376///
377/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
378/// or if no terminating token is found (a non alphabetic character).
379/// # Example
380///
381/// ```
382/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
383/// # use nom8::character::streaming::alpha0;
384/// assert_eq!(alpha0::<_, (_, ErrorKind)>("ab1c"), Ok(("1c", "ab")));
385/// assert_eq!(alpha0::<_, (_, ErrorKind)>("1c"), Ok(("1c", "")));
386/// assert_eq!(alpha0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
387/// ```
388///
389/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha0`][crate::character::alpha0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
390#[deprecated(
391  since = "8.0.0",
392  note = "Replaced with `nom8::character::alpha0` with input wrapped in `nom8::input::Streaming`"
393)]
394pub fn alpha0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
395where
396  T: InputTakeAtPosition,
397  T: IntoOutput,
398  <T as InputTakeAtPosition>::Item: AsChar,
399{
400  input
401    .split_at_position_streaming(|item| !item.is_alpha())
402    .into_output()
403}
404
405/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
406///
407/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
408/// or if no terminating token is found (a non alphabetic character).
409/// # Example
410///
411/// ```
412/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
413/// # use nom8::character::streaming::alpha1;
414/// assert_eq!(alpha1::<_, (_, ErrorKind)>("aB1c"), Ok(("1c", "aB")));
415/// assert_eq!(alpha1::<_, (_, ErrorKind)>("1c"), Err(Err::Error(("1c", ErrorKind::Alpha))));
416/// assert_eq!(alpha1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
417/// ```
418///
419/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha1`][crate::character::alpha1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
420#[deprecated(
421  since = "8.0.0",
422  note = "Replaced with `nom8::character::alpha1` with input wrapped in `nom8::input::Streaming`"
423)]
424pub fn alpha1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
425where
426  T: InputTakeAtPosition,
427  T: IntoOutput,
428  <T as InputTakeAtPosition>::Item: AsChar,
429{
430  input
431    .split_at_position1_streaming(|item| !item.is_alpha(), ErrorKind::Alpha)
432    .into_output()
433}
434
435/// Recognizes zero or more ASCII numerical characters: 0-9
436///
437/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
438/// or if no terminating token is found (a non digit character).
439/// # Example
440///
441/// ```
442/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
443/// # use nom8::character::streaming::digit0;
444/// assert_eq!(digit0::<_, (_, ErrorKind)>("21c"), Ok(("c", "21")));
445/// assert_eq!(digit0::<_, (_, ErrorKind)>("a21c"), Ok(("a21c", "")));
446/// assert_eq!(digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
447/// ```
448///
449/// **WARNING:** Deprecated, replaced with [`nom8::character::digit0`][crate::character::digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
450#[deprecated(
451  since = "8.0.0",
452  note = "Replaced with `nom8::character::digit0` with input wrapped in `nom8::input::Streaming`"
453)]
454pub fn digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
455where
456  T: InputTakeAtPosition,
457  T: IntoOutput,
458  <T as InputTakeAtPosition>::Item: AsChar,
459{
460  input
461    .split_at_position_streaming(|item| !item.is_dec_digit())
462    .into_output()
463}
464
465/// Recognizes one or more ASCII numerical characters: 0-9
466///
467/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
468/// or if no terminating token is found (a non digit character).
469/// # Example
470///
471/// ```
472/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
473/// # use nom8::character::streaming::digit1;
474/// assert_eq!(digit1::<_, (_, ErrorKind)>("21c"), Ok(("c", "21")));
475/// assert_eq!(digit1::<_, (_, ErrorKind)>("c1"), Err(Err::Error(("c1", ErrorKind::Digit))));
476/// assert_eq!(digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
477/// ```
478///
479/// **WARNING:** Deprecated, replaced with [`nom8::character::digit1`][crate::character::digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
480#[deprecated(
481  since = "8.0.0",
482  note = "Replaced with `nom8::character::digit1` with input wrapped in `nom8::input::Streaming`"
483)]
484pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
485where
486  T: InputTakeAtPosition,
487  T: IntoOutput,
488  <T as InputTakeAtPosition>::Item: AsChar,
489{
490  input
491    .split_at_position1_streaming(|item| !item.is_dec_digit(), ErrorKind::Digit)
492    .into_output()
493}
494
495/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
496///
497/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
498/// or if no terminating token is found (a non hexadecimal digit character).
499/// # Example
500///
501/// ```
502/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
503/// # use nom8::character::streaming::hex_digit0;
504/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c")));
505/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
506/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
507/// ```
508///
509/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit0`][crate::character::hex_digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
510#[deprecated(
511  since = "8.0.0",
512  note = "Replaced with `nom8::character::hex_digit0` with input wrapped in `nom8::input::Streaming`"
513)]
514pub fn hex_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
515where
516  T: InputTakeAtPosition,
517  T: IntoOutput,
518  <T as InputTakeAtPosition>::Item: AsChar,
519{
520  input
521    .split_at_position_streaming(|item| !item.is_hex_digit())
522    .into_output()
523}
524
525/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
526///
527/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
528/// or if no terminating token is found (a non hexadecimal digit character).
529/// # Example
530///
531/// ```
532/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
533/// # use nom8::character::streaming::hex_digit1;
534/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c")));
535/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::HexDigit))));
536/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
537/// ```
538///
539/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit1`][crate::character::hex_digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
540#[deprecated(
541  since = "8.0.0",
542  note = "Replaced with `nom8::character::hex_digit1` with input wrapped in `nom8::input::Streaming`"
543)]
544pub fn hex_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
545where
546  T: InputTakeAtPosition,
547  T: IntoOutput,
548  <T as InputTakeAtPosition>::Item: AsChar,
549{
550  input
551    .split_at_position1_streaming(|item| !item.is_hex_digit(), ErrorKind::HexDigit)
552    .into_output()
553}
554
555/// Recognizes zero or more octal characters: 0-7
556///
557/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
558/// or if no terminating token is found (a non octal digit character).
559/// # Example
560///
561/// ```
562/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
563/// # use nom8::character::streaming::oct_digit0;
564/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21")));
565/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
566/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
567/// ```
568///
569/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit0`][crate::character::oct_digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
570#[deprecated(
571  since = "8.0.0",
572  note = "Replaced with `nom8::character::oct_digit0` with input wrapped in `nom8::input::Streaming`"
573)]
574pub fn oct_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
575where
576  T: InputTakeAtPosition,
577  T: IntoOutput,
578  <T as InputTakeAtPosition>::Item: AsChar,
579{
580  input
581    .split_at_position_streaming(|item| !item.is_oct_digit())
582    .into_output()
583}
584
585/// Recognizes one or more octal characters: 0-7
586///
587/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
588/// or if no terminating token is found (a non octal digit character).
589/// # Example
590///
591/// ```
592/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
593/// # use nom8::character::streaming::oct_digit1;
594/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21")));
595/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::OctDigit))));
596/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
597/// ```
598///
599/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit1`][crate::character::oct_digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
600#[deprecated(
601  since = "8.0.0",
602  note = "Replaced with `nom8::character::oct_digit1` with input wrapped in `nom8::input::Streaming`"
603)]
604pub fn oct_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
605where
606  T: InputTakeAtPosition,
607  T: IntoOutput,
608  <T as InputTakeAtPosition>::Item: AsChar,
609{
610  input
611    .split_at_position1_streaming(|item| !item.is_oct_digit(), ErrorKind::OctDigit)
612    .into_output()
613}
614
615/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
616///
617/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
618/// or if no terminating token is found (a non alphanumerical character).
619/// # Example
620///
621/// ```
622/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
623/// # use nom8::character::streaming::alphanumeric0;
624/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ")));
625/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("&Z21c"), Ok(("&Z21c", "")));
626/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
627/// ```
628///
629/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric0`][crate::character::alphanumeric0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
630#[deprecated(
631  since = "8.0.0",
632  note = "Replaced with `nom8::character::alphanumeric0` with input wrapped in `nom8::input::Streaming`"
633)]
634pub fn alphanumeric0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
635where
636  T: InputTakeAtPosition,
637  T: IntoOutput,
638  <T as InputTakeAtPosition>::Item: AsChar,
639{
640  input
641    .split_at_position_streaming(|item| !item.is_alphanum())
642    .into_output()
643}
644
645/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
646///
647/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
648/// or if no terminating token is found (a non alphanumerical character).
649/// # Example
650///
651/// ```
652/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
653/// # use nom8::character::streaming::alphanumeric1;
654/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ")));
655/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("&H2"), Err(Err::Error(("&H2", ErrorKind::AlphaNumeric))));
656/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
657/// ```
658///
659/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric1`][crate::character::alphanumeric1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
660#[deprecated(
661  since = "8.0.0",
662  note = "Replaced with `nom8::character::alphanumeric1` with input wrapped in `nom8::input::Streaming`"
663)]
664pub fn alphanumeric1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
665where
666  T: InputTakeAtPosition,
667  T: IntoOutput,
668  <T as InputTakeAtPosition>::Item: AsChar,
669{
670  input
671    .split_at_position1_streaming(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric)
672    .into_output()
673}
674
675/// Recognizes zero or more spaces and tabs.
676///
677/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
678/// or if no terminating token is found (a non space character).
679/// # Example
680///
681/// ```
682/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
683/// # use nom8::character::streaming::space0;
684/// assert_eq!(space0::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t")));
685/// assert_eq!(space0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
686/// assert_eq!(space0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
687/// ```
688///
689/// **WARNING:** Deprecated, replaced with [`nom8::character::space0`][crate::character::space0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
690#[deprecated(
691  since = "8.0.0",
692  note = "Replaced with `nom8::character::space0` with input wrapped in `nom8::input::Streaming`"
693)]
694pub fn space0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
695where
696  T: InputTakeAtPosition,
697  T: IntoOutput,
698  <T as InputTakeAtPosition>::Item: AsChar + Clone,
699{
700  input
701    .split_at_position_streaming(|item| {
702      let c = item.as_char();
703      !(c == ' ' || c == '\t')
704    })
705    .into_output()
706}
707/// Recognizes one or more spaces and tabs.
708///
709/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
710/// or if no terminating token is found (a non space character).
711/// # Example
712///
713/// ```
714/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
715/// # use nom8::character::streaming::space1;
716/// assert_eq!(space1::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t")));
717/// assert_eq!(space1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::Space))));
718/// assert_eq!(space1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
719/// ```
720///
721/// **WARNING:** Deprecated, replaced with [`nom8::character::space1`][crate::character::space1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
722#[deprecated(
723  since = "8.0.0",
724  note = "Replaced with `nom8::character::space1` with input wrapped in `nom8::input::Streaming`"
725)]
726pub fn space1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
727where
728  T: InputTakeAtPosition,
729  T: IntoOutput,
730  <T as InputTakeAtPosition>::Item: AsChar + Clone,
731{
732  input
733    .split_at_position1_streaming(
734      |item| {
735        let c = item.as_char();
736        !(c == ' ' || c == '\t')
737      },
738      ErrorKind::Space,
739    )
740    .into_output()
741}
742
743/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
744///
745/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
746/// or if no terminating token is found (a non space character).
747/// # Example
748///
749/// ```
750/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
751/// # use nom8::character::streaming::multispace0;
752/// assert_eq!(multispace0::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
753/// assert_eq!(multispace0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
754/// assert_eq!(multispace0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
755/// ```
756///
757/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace0`][crate::character::multispace0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
758#[deprecated(
759  since = "8.0.0",
760  note = "Replaced with `nom8::character::multispace0` with input wrapped in `nom8::input::Streaming`"
761)]
762pub fn multispace0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
763where
764  T: InputTakeAtPosition,
765  T: IntoOutput,
766  <T as InputTakeAtPosition>::Item: AsChar + Clone,
767{
768  input
769    .split_at_position_streaming(|item| {
770      let c = item.as_char();
771      !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
772    })
773    .into_output()
774}
775
776/// Recognizes one or more spaces, tabs, carriage returns and line feeds.
777///
778/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
779/// or if no terminating token is found (a non space character).
780/// # Example
781///
782/// ```
783/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
784/// # use nom8::character::streaming::multispace1;
785/// assert_eq!(multispace1::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
786/// assert_eq!(multispace1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::MultiSpace))));
787/// assert_eq!(multispace1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
788/// ```
789///
790/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace1`][crate::character::multispace1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
791#[deprecated(
792  since = "8.0.0",
793  note = "Replaced with `nom8::character::multispace1` with input wrapped in `nom8::input::Streaming`"
794)]
795pub fn multispace1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
796where
797  T: InputTakeAtPosition,
798  T: IntoOutput,
799  <T as InputTakeAtPosition>::Item: AsChar + Clone,
800{
801  input
802    .split_at_position1_streaming(
803      |item| {
804        let c = item.as_char();
805        !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
806      },
807      ErrorKind::MultiSpace,
808    )
809    .into_output()
810}
811
812pub(crate) fn sign<T, E: ParseError<T>>(input: T) -> IResult<T, bool, E>
813where
814  T: Clone + InputTake + InputLength,
815  T: IntoOutput,
816  T: for<'a> Compare<&'a [u8]>,
817{
818  use crate::bytes::streaming::tag;
819  use crate::combinator::value;
820
821  let (i, opt_sign) = opt(alt((
822    value(false, tag(&b"-"[..])),
823    value(true, tag(&b"+"[..])),
824  )))(input)?;
825  let sign = opt_sign.unwrap_or(true);
826
827  Ok((i, sign))
828}
829
830#[doc(hidden)]
831macro_rules! ints {
832    ($($t:tt)+) => {
833        $(
834        /// will parse a number in text form to a number
835        ///
836        /// *Complete version*: can parse until the end of input.
837        pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
838            where
839            T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputTake + Clone,
840            T: IntoOutput,
841            <T as InputIter>::Item: AsChar,
842            T: for <'a> Compare<&'a[u8]>,
843            {
844              let (i, sign) = sign(input.clone())?;
845
846                if i.input_len() == 0 {
847                    return Err(Err::Incomplete(Needed::new(1)));
848                }
849
850                let mut value: $t = 0;
851                if sign {
852                    for (pos, c) in i.iter_indices() {
853                        match c.as_char().to_digit(10) {
854                            None => {
855                                if pos == 0 {
856                                    return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
857                                } else {
858                                    return Ok((i.slice(pos..), value));
859                                }
860                            },
861                            Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
862                                None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
863                                Some(v) => value = v,
864                            }
865                        }
866                    }
867                } else {
868                    for (pos, c) in i.iter_indices() {
869                        match c.as_char().to_digit(10) {
870                            None => {
871                                if pos == 0 {
872                                    return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
873                                } else {
874                                    return Ok((i.slice(pos..), value));
875                                }
876                            },
877                            Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) {
878                                None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
879                                Some(v) => value = v,
880                            }
881                        }
882                    }
883                }
884
885                Err(Err::Incomplete(Needed::new(1)))
886            }
887        )+
888    }
889}
890
891ints! { i8 i16 i32 i64 i128 }
892
893#[doc(hidden)]
894macro_rules! uints {
895    ($($t:tt)+) => {
896        $(
897        /// will parse a number in text form to a number
898        ///
899        /// *Complete version*: can parse until the end of input.
900        pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
901            where
902            T: InputIter + Slice<RangeFrom<usize>> + InputLength,
903            T: IntoOutput,
904            <T as InputIter>::Item: AsChar,
905            {
906                let i = input;
907
908                if i.input_len() == 0 {
909                    return Err(Err::Incomplete(Needed::new(1)));
910                }
911
912                let mut value: $t = 0;
913                for (pos, c) in i.iter_indices() {
914                    match c.as_char().to_digit(10) {
915                        None => {
916                            if pos == 0 {
917                                return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit)));
918                            } else {
919                                return Ok((i.slice(pos..), value));
920                            }
921                        },
922                        Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
923                            None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))),
924                            Some(v) => value = v,
925                        }
926                    }
927                }
928
929                Err(Err::Incomplete(Needed::new(1)))
930            }
931        )+
932    }
933}
934
935uints! { u8 u16 u32 u64 u128 }
936
937#[cfg(test)]
938mod tests {
939  use super::*;
940  use crate::error::ErrorKind;
941  use crate::input::ParseTo;
942  use crate::sequence::pair;
943  use crate::{Err, IResult, Needed};
944  use proptest::prelude::*;
945
946  macro_rules! assert_parse(
947    ($left: expr, $right: expr) => {
948      let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
949      assert_eq!(res, $right);
950    };
951  );
952
953  #[test]
954  fn anychar_str() {
955    use super::anychar;
956    assert_eq!(anychar::<_, (&str, ErrorKind)>("Ә"), Ok(("", 'Ә')));
957  }
958
959  #[test]
960  fn character() {
961    let a: &[u8] = b"abcd";
962    let b: &[u8] = b"1234";
963    let c: &[u8] = b"a123";
964    let d: &[u8] = "azé12".as_bytes();
965    let e: &[u8] = b" ";
966    let f: &[u8] = b" ;";
967    //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::new(1))));
968    assert_parse!(alpha1(a), Err(Err::Incomplete(Needed::new(1))));
969    assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
970    assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..])));
971    assert_eq!(
972      alpha1::<_, (_, ErrorKind)>(d),
973      Ok(("é12".as_bytes(), &b"az"[..]))
974    );
975    assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
976    assert_eq!(
977      digit1::<_, (_, ErrorKind)>(b),
978      Err(Err::Incomplete(Needed::new(1)))
979    );
980    assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
981    assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
982    assert_eq!(
983      hex_digit1::<_, (_, ErrorKind)>(a),
984      Err(Err::Incomplete(Needed::new(1)))
985    );
986    assert_eq!(
987      hex_digit1::<_, (_, ErrorKind)>(b),
988      Err(Err::Incomplete(Needed::new(1)))
989    );
990    assert_eq!(
991      hex_digit1::<_, (_, ErrorKind)>(c),
992      Err(Err::Incomplete(Needed::new(1)))
993    );
994    assert_eq!(
995      hex_digit1::<_, (_, ErrorKind)>(d),
996      Ok(("zé12".as_bytes(), &b"a"[..]))
997    );
998    assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
999    assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
1000    assert_eq!(
1001      oct_digit1::<_, (_, ErrorKind)>(b),
1002      Err(Err::Incomplete(Needed::new(1)))
1003    );
1004    assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
1005    assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
1006    assert_eq!(
1007      alphanumeric1::<_, (_, ErrorKind)>(a),
1008      Err(Err::Incomplete(Needed::new(1)))
1009    );
1010    //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
1011    assert_eq!(
1012      alphanumeric1::<_, (_, ErrorKind)>(c),
1013      Err(Err::Incomplete(Needed::new(1)))
1014    );
1015    assert_eq!(
1016      alphanumeric1::<_, (_, ErrorKind)>(d),
1017      Ok(("é12".as_bytes(), &b"az"[..]))
1018    );
1019    assert_eq!(
1020      space1::<_, (_, ErrorKind)>(e),
1021      Err(Err::Incomplete(Needed::new(1)))
1022    );
1023    assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..])));
1024  }
1025
1026  #[cfg(feature = "alloc")]
1027  #[test]
1028  fn character_s() {
1029    let a = "abcd";
1030    let b = "1234";
1031    let c = "a123";
1032    let d = "azé12";
1033    let e = " ";
1034    assert_eq!(
1035      alpha1::<_, (_, ErrorKind)>(a),
1036      Err(Err::Incomplete(Needed::new(1)))
1037    );
1038    assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
1039    assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..])));
1040    assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..])));
1041    assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
1042    assert_eq!(
1043      digit1::<_, (_, ErrorKind)>(b),
1044      Err(Err::Incomplete(Needed::new(1)))
1045    );
1046    assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
1047    assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
1048    assert_eq!(
1049      hex_digit1::<_, (_, ErrorKind)>(a),
1050      Err(Err::Incomplete(Needed::new(1)))
1051    );
1052    assert_eq!(
1053      hex_digit1::<_, (_, ErrorKind)>(b),
1054      Err(Err::Incomplete(Needed::new(1)))
1055    );
1056    assert_eq!(
1057      hex_digit1::<_, (_, ErrorKind)>(c),
1058      Err(Err::Incomplete(Needed::new(1)))
1059    );
1060    assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..])));
1061    assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
1062    assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
1063    assert_eq!(
1064      oct_digit1::<_, (_, ErrorKind)>(b),
1065      Err(Err::Incomplete(Needed::new(1)))
1066    );
1067    assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
1068    assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
1069    assert_eq!(
1070      alphanumeric1::<_, (_, ErrorKind)>(a),
1071      Err(Err::Incomplete(Needed::new(1)))
1072    );
1073    //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
1074    assert_eq!(
1075      alphanumeric1::<_, (_, ErrorKind)>(c),
1076      Err(Err::Incomplete(Needed::new(1)))
1077    );
1078    assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az")));
1079    assert_eq!(
1080      space1::<_, (_, ErrorKind)>(e),
1081      Err(Err::Incomplete(Needed::new(1)))
1082    );
1083  }
1084
1085  use crate::input::Offset;
1086  #[test]
1087  fn offset() {
1088    let a = &b"abcd;"[..];
1089    let b = &b"1234;"[..];
1090    let c = &b"a123;"[..];
1091    let d = &b" \t;"[..];
1092    let e = &b" \t\r\n;"[..];
1093    let f = &b"123abcDEF;"[..];
1094
1095    match alpha1::<_, (_, ErrorKind)>(a) {
1096      Ok((i, _)) => {
1097        assert_eq!(a.offset(i) + i.len(), a.len());
1098      }
1099      _ => panic!("wrong return type in offset test for alpha"),
1100    }
1101    match digit1::<_, (_, ErrorKind)>(b) {
1102      Ok((i, _)) => {
1103        assert_eq!(b.offset(i) + i.len(), b.len());
1104      }
1105      _ => panic!("wrong return type in offset test for digit"),
1106    }
1107    match alphanumeric1::<_, (_, ErrorKind)>(c) {
1108      Ok((i, _)) => {
1109        assert_eq!(c.offset(i) + i.len(), c.len());
1110      }
1111      _ => panic!("wrong return type in offset test for alphanumeric"),
1112    }
1113    match space1::<_, (_, ErrorKind)>(d) {
1114      Ok((i, _)) => {
1115        assert_eq!(d.offset(i) + i.len(), d.len());
1116      }
1117      _ => panic!("wrong return type in offset test for space"),
1118    }
1119    match multispace1::<_, (_, ErrorKind)>(e) {
1120      Ok((i, _)) => {
1121        assert_eq!(e.offset(i) + i.len(), e.len());
1122      }
1123      _ => panic!("wrong return type in offset test for multispace"),
1124    }
1125    match hex_digit1::<_, (_, ErrorKind)>(f) {
1126      Ok((i, _)) => {
1127        assert_eq!(f.offset(i) + i.len(), f.len());
1128      }
1129      _ => panic!("wrong return type in offset test for hex_digit"),
1130    }
1131    match oct_digit1::<_, (_, ErrorKind)>(f) {
1132      Ok((i, _)) => {
1133        assert_eq!(f.offset(i) + i.len(), f.len());
1134      }
1135      _ => panic!("wrong return type in offset test for oct_digit"),
1136    }
1137  }
1138
1139  #[test]
1140  fn is_not_line_ending_bytes() {
1141    let a: &[u8] = b"ab12cd\nefgh";
1142    assert_eq!(
1143      not_line_ending::<_, (_, ErrorKind)>(a),
1144      Ok((&b"\nefgh"[..], &b"ab12cd"[..]))
1145    );
1146
1147    let b: &[u8] = b"ab12cd\nefgh\nijkl";
1148    assert_eq!(
1149      not_line_ending::<_, (_, ErrorKind)>(b),
1150      Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..]))
1151    );
1152
1153    let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
1154    assert_eq!(
1155      not_line_ending::<_, (_, ErrorKind)>(c),
1156      Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..]))
1157    );
1158
1159    let d: &[u8] = b"ab12cd";
1160    assert_eq!(
1161      not_line_ending::<_, (_, ErrorKind)>(d),
1162      Err(Err::Incomplete(Needed::Unknown))
1163    );
1164  }
1165
1166  #[test]
1167  fn is_not_line_ending_str() {
1168    /*
1169    let a: &str = "ab12cd\nefgh";
1170    assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..])));
1171
1172    let b: &str = "ab12cd\nefgh\nijkl";
1173    assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..])));
1174
1175    let c: &str = "ab12cd\r\nefgh\nijkl";
1176    assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..])));
1177
1178    let d = "βèƒôřè\nÂßÇáƒƭèř";
1179    assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
1180
1181    let e = "βèƒôřè\r\nÂßÇáƒƭèř";
1182    assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
1183    */
1184
1185    let f = "βèƒôřè\rÂßÇáƒƭèř";
1186    assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag))));
1187
1188    let g2: &str = "ab12cd";
1189    assert_eq!(
1190      not_line_ending::<_, (_, ErrorKind)>(g2),
1191      Err(Err::Incomplete(Needed::Unknown))
1192    );
1193  }
1194
1195  #[test]
1196  fn hex_digit_test() {
1197    let i = &b"0123456789abcdefABCDEF;"[..];
1198    assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
1199
1200    let i = &b"g"[..];
1201    assert_parse!(
1202      hex_digit1(i),
1203      Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
1204    );
1205
1206    let i = &b"G"[..];
1207    assert_parse!(
1208      hex_digit1(i),
1209      Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
1210    );
1211
1212    assert!(AsChar::is_hex_digit(b'0'));
1213    assert!(AsChar::is_hex_digit(b'9'));
1214    assert!(AsChar::is_hex_digit(b'a'));
1215    assert!(AsChar::is_hex_digit(b'f'));
1216    assert!(AsChar::is_hex_digit(b'A'));
1217    assert!(AsChar::is_hex_digit(b'F'));
1218    assert!(!AsChar::is_hex_digit(b'g'));
1219    assert!(!AsChar::is_hex_digit(b'G'));
1220    assert!(!AsChar::is_hex_digit(b'/'));
1221    assert!(!AsChar::is_hex_digit(b':'));
1222    assert!(!AsChar::is_hex_digit(b'@'));
1223    assert!(!AsChar::is_hex_digit(b'\x60'));
1224  }
1225
1226  #[test]
1227  fn oct_digit_test() {
1228    let i = &b"01234567;"[..];
1229    assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
1230
1231    let i = &b"8"[..];
1232    assert_parse!(
1233      oct_digit1(i),
1234      Err(Err::Error(error_position!(i, ErrorKind::OctDigit)))
1235    );
1236
1237    assert!(AsChar::is_oct_digit(b'0'));
1238    assert!(AsChar::is_oct_digit(b'7'));
1239    assert!(!AsChar::is_oct_digit(b'8'));
1240    assert!(!AsChar::is_oct_digit(b'9'));
1241    assert!(!AsChar::is_oct_digit(b'a'));
1242    assert!(!AsChar::is_oct_digit(b'A'));
1243    assert!(!AsChar::is_oct_digit(b'/'));
1244    assert!(!AsChar::is_oct_digit(b':'));
1245    assert!(!AsChar::is_oct_digit(b'@'));
1246    assert!(!AsChar::is_oct_digit(b'\x60'));
1247  }
1248
1249  #[test]
1250  fn full_line_windows() {
1251    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
1252      pair(not_line_ending, line_ending)(i)
1253    }
1254    let input = b"abc\r\n";
1255    let output = take_full_line(input);
1256    assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
1257  }
1258
1259  #[test]
1260  fn full_line_unix() {
1261    fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
1262      pair(not_line_ending, line_ending)(i)
1263    }
1264    let input = b"abc\n";
1265    let output = take_full_line(input);
1266    assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
1267  }
1268
1269  #[test]
1270  fn check_windows_lineending() {
1271    let input = b"\r\n";
1272    let output = line_ending(&input[..]);
1273    assert_parse!(output, Ok((&b""[..], &b"\r\n"[..])));
1274  }
1275
1276  #[test]
1277  fn check_unix_lineending() {
1278    let input = b"\n";
1279    let output = line_ending(&input[..]);
1280    assert_parse!(output, Ok((&b""[..], &b"\n"[..])));
1281  }
1282
1283  #[test]
1284  fn cr_lf() {
1285    assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
1286    assert_parse!(crlf(&b"\r"[..]), Err(Err::Incomplete(Needed::new(2))));
1287    assert_parse!(
1288      crlf(&b"\ra"[..]),
1289      Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
1290    );
1291
1292    assert_parse!(crlf("\r\na"), Ok(("a", "\r\n")));
1293    assert_parse!(crlf("\r"), Err(Err::Incomplete(Needed::new(2))));
1294    assert_parse!(
1295      crlf("\ra"),
1296      Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
1297    );
1298  }
1299
1300  #[test]
1301  fn end_of_line() {
1302    assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..])));
1303    assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
1304    assert_parse!(
1305      line_ending(&b"\r"[..]),
1306      Err(Err::Incomplete(Needed::new(2)))
1307    );
1308    assert_parse!(
1309      line_ending(&b"\ra"[..]),
1310      Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
1311    );
1312
1313    assert_parse!(line_ending("\na"), Ok(("a", "\n")));
1314    assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n")));
1315    assert_parse!(line_ending("\r"), Err(Err::Incomplete(Needed::new(2))));
1316    assert_parse!(
1317      line_ending("\ra"),
1318      Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
1319    );
1320  }
1321
1322  fn digit_to_i16(input: &str) -> IResult<&str, i16> {
1323    let i = input;
1324    let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?;
1325    let sign = match opt_sign {
1326      Some('+') => true,
1327      Some('-') => false,
1328      _ => true,
1329    };
1330
1331    let (i, s) = match digit1::<_, crate::error::Error<_>>(i) {
1332      Ok((i, s)) => (i, s),
1333      Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)),
1334      Err(_) => {
1335        return Err(Err::Error(crate::error::Error::from_error_kind(
1336          input,
1337          ErrorKind::Digit,
1338        )))
1339      }
1340    };
1341    match s.parse_to() {
1342      Some(n) => {
1343        if sign {
1344          Ok((i, n))
1345        } else {
1346          Ok((i, -n))
1347        }
1348      }
1349      None => Err(Err::Error(crate::error::Error::from_error_kind(
1350        i,
1351        ErrorKind::Digit,
1352      ))),
1353    }
1354  }
1355
1356  fn digit_to_u32(i: &str) -> IResult<&str, u32> {
1357    let (i, s) = digit1(i)?;
1358    match s.parse_to() {
1359      Some(n) => Ok((i, n)),
1360      None => Err(Err::Error(crate::error::Error::from_error_kind(
1361        i,
1362        ErrorKind::Digit,
1363      ))),
1364    }
1365  }
1366
1367  #[test]
1368  fn one_of_test() {
1369    fn f(i: &[u8]) -> IResult<&[u8], char> {
1370      one_of("ab")(i)
1371    }
1372
1373    let a = &b"abcd"[..];
1374    assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));
1375
1376    let b = &b"cde"[..];
1377    assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));
1378
1379    fn utf8(i: &str) -> IResult<&str, char> {
1380      one_of("+\u{FF0B}")(i)
1381    }
1382
1383    assert!(utf8("+").is_ok());
1384    assert!(utf8("\u{FF0B}").is_ok());
1385  }
1386
1387  #[test]
1388  fn none_of_test() {
1389    fn f(i: &[u8]) -> IResult<&[u8], char> {
1390      none_of("ab")(i)
1391    }
1392
1393    let a = &b"abcd"[..];
1394    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));
1395
1396    let b = &b"cde"[..];
1397    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
1398  }
1399
1400  #[test]
1401  fn char_byteslice() {
1402    fn f(i: &[u8]) -> IResult<&[u8], char> {
1403      char('c')(i)
1404    }
1405
1406    let a = &b"abcd"[..];
1407    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
1408
1409    let b = &b"cde"[..];
1410    assert_eq!(f(b), Ok((&b"de"[..], 'c')));
1411  }
1412
1413  #[test]
1414  fn char_str() {
1415    fn f(i: &str) -> IResult<&str, char> {
1416      char('c')(i)
1417    }
1418
1419    let a = &"abcd"[..];
1420    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
1421
1422    let b = &"cde"[..];
1423    assert_eq!(f(b), Ok((&"de"[..], 'c')));
1424  }
1425
1426  proptest! {
1427    #[test]
1428    fn ints(s in "\\PC*") {
1429        let res1 = digit_to_i16(&s);
1430        let res2 = i16(s.as_str());
1431        assert_eq!(res1, res2);
1432    }
1433
1434    #[test]
1435    fn uints(s in "\\PC*") {
1436        let res1 = digit_to_u32(&s);
1437        let res2 = u32(s.as_str());
1438        assert_eq!(res1, res2);
1439    }
1440  }
1441}