nom8/character/
complete.rs

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