nom8/character/
mod.rs

1//! Character specific parsers and combinators
2//!
3//! Functions recognizing specific characters
4
5#![allow(deprecated)] // will just become `pub(crate)` later
6
7pub mod complete;
8pub mod streaming;
9#[cfg(test)]
10mod tests;
11
12use crate::error::ParseError;
13use crate::input::Compare;
14use crate::input::{
15  AsBytes, AsChar, InputIsStreaming, InputIter, InputLength, InputTake, InputTakeAtPosition,
16  IntoOutput, Offset, ParseTo, Slice,
17};
18use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
19use crate::IResult;
20
21/// Recognizes the string "\r\n".
22///
23/// *Complete version*: Will return an error if there's not enough input data.
24///
25/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
26///
27/// # Example
28///
29/// ```
30/// # use nom8::{Err, error::{Error, ErrorKind}, IResult};
31/// # use nom8::character::crlf;
32/// fn parser(input: &str) -> IResult<&str, &str> {
33///     crlf(input)
34/// }
35///
36/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
37/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
38/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
39/// ```
40///
41/// ```
42/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
43/// # use nom8::input::Streaming;
44/// # use nom8::character::crlf;
45/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Ok((Streaming("c"), "\r\n")));
46/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Err(Err::Error((Streaming("ab\r\nc"), ErrorKind::CrLf))));
47/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(2))));
48/// ```
49#[inline(always)]
50pub fn crlf<T, E: ParseError<T>, const STREAMING: bool>(
51  input: T,
52) -> IResult<T, <T as IntoOutput>::Output, E>
53where
54  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
55  T: InputIter + InputIsStreaming<STREAMING>,
56  T: IntoOutput,
57  T: Compare<&'static str>,
58{
59  if STREAMING {
60    streaming::crlf(input)
61  } else {
62    complete::crlf(input)
63  }
64}
65
66/// Recognizes a string of any char except '\r\n' or '\n'.
67///
68/// *Complete version*: Will return an error if there's not enough input data.
69///
70/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
71///
72/// # Example
73///
74/// ```
75/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
76/// # use nom8::character::not_line_ending;
77/// fn parser(input: &str) -> IResult<&str, &str> {
78///     not_line_ending(input)
79/// }
80///
81/// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab")));
82/// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab")));
83/// assert_eq!(parser("abc"), Ok(("", "abc")));
84/// assert_eq!(parser(""), Ok(("", "")));
85/// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag })));
86/// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag })));
87/// ```
88///
89/// ```
90/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
91/// # use nom8::input::Streaming;
92/// # use nom8::character::not_line_ending;
93/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Ok((Streaming("\r\nc"), "ab")));
94/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("abc")), Err(Err::Incomplete(Needed::Unknown)));
95/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::Unknown)));
96/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("a\rb\nc")), Err(Err::Error((Streaming("a\rb\nc"), ErrorKind::Tag ))));
97/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("a\rbc")), Err(Err::Error((Streaming("a\rbc"), ErrorKind::Tag ))));
98/// ```
99#[inline(always)]
100pub fn not_line_ending<T, E: ParseError<T>, const STREAMING: bool>(
101  input: T,
102) -> IResult<T, <T as IntoOutput>::Output, E>
103where
104  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
105  T: InputIter + InputLength + InputIsStreaming<STREAMING>,
106  T: IntoOutput,
107  T: Compare<&'static str>,
108  <T as InputIter>::Item: AsChar,
109  <T as InputIter>::Item: AsChar,
110{
111  if STREAMING {
112    streaming::not_line_ending(input)
113  } else {
114    complete::not_line_ending(input)
115  }
116}
117
118/// Recognizes an end of line (both '\n' and '\r\n').
119///
120/// *Complete version*: Will return an error if there's not enough input data.
121///
122/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
123///
124/// # Example
125///
126/// ```
127/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
128/// # use nom8::character::line_ending;
129/// fn parser(input: &str) -> IResult<&str, &str> {
130///     line_ending(input)
131/// }
132///
133/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
134/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
135/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
136/// ```
137///
138/// ```
139/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
140/// # use nom8::input::Streaming;
141/// # use nom8::character::line_ending;
142/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Ok((Streaming("c"), "\r\n")));
143/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Err(Err::Error((Streaming("ab\r\nc"), ErrorKind::CrLf))));
144/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
145/// ```
146#[inline(always)]
147pub fn line_ending<T, E: ParseError<T>, const STREAMING: bool>(
148  input: T,
149) -> IResult<T, <T as IntoOutput>::Output, E>
150where
151  T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
152  T: InputIter + InputLength + InputIsStreaming<STREAMING>,
153  T: IntoOutput,
154  T: Compare<&'static str>,
155{
156  if STREAMING {
157    streaming::line_ending(input)
158  } else {
159    complete::line_ending(input)
160  }
161}
162
163/// Matches a newline character '\n'.
164///
165/// *Complete version*: Will return an error if there's not enough input data.
166///
167/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
168///
169/// # Example
170///
171/// ```
172/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
173/// # use nom8::character::newline;
174/// fn parser(input: &str) -> IResult<&str, char> {
175///     newline(input)
176/// }
177///
178/// assert_eq!(parser("\nc"), Ok(("c", '\n')));
179/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
180/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
181/// ```
182///
183/// ```
184/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
185/// # use nom8::input::Streaming;
186/// # use nom8::character::newline;
187/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("\nc")), Ok((Streaming("c"), '\n')));
188/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Err(Err::Error((Streaming("\r\nc"), ErrorKind::Char))));
189/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
190/// ```
191#[inline(always)]
192pub fn newline<I, Error: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, char, Error>
193where
194  I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
195  <I as InputIter>::Item: AsChar,
196{
197  if STREAMING {
198    streaming::newline(input)
199  } else {
200    complete::newline(input)
201  }
202}
203
204/// Matches a tab character '\t'.
205///
206/// *Complete version*: Will return an error if there's not enough input data.
207///
208/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
209///
210/// # Example
211///
212/// ```
213/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
214/// # use nom8::character::tab;
215/// fn parser(input: &str) -> IResult<&str, char> {
216///     tab(input)
217/// }
218///
219/// assert_eq!(parser("\tc"), Ok(("c", '\t')));
220/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
221/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
222/// ```
223///
224/// ```
225/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
226/// # use nom8::input::Streaming;
227/// # use nom8::character::tab;
228/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("\tc")), Ok((Streaming("c"), '\t')));
229/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Err(Err::Error((Streaming("\r\nc"), ErrorKind::Char))));
230/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
231/// ```
232#[inline(always)]
233pub fn tab<I, Error: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, char, Error>
234where
235  I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
236  <I as InputIter>::Item: AsChar,
237{
238  if STREAMING {
239    streaming::tab(input)
240  } else {
241    complete::tab(input)
242  }
243}
244
245/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
246///
247/// *Complete version*: Will return the whole input if no terminating token is found (a non
248/// alphabetic character).
249///
250/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
251/// or if no terminating token is found (a non alphabetic character).
252///
253/// # Example
254///
255/// ```
256/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
257/// # use nom8::character::alpha0;
258/// fn parser(input: &str) -> IResult<&str, &str> {
259///     alpha0(input)
260/// }
261///
262/// assert_eq!(parser("ab1c"), Ok(("1c", "ab")));
263/// assert_eq!(parser("1c"), Ok(("1c", "")));
264/// assert_eq!(parser(""), Ok(("", "")));
265/// ```
266///
267/// ```
268/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
269/// # use nom8::input::Streaming;
270/// # use nom8::character::alpha0;
271/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("ab1c")), Ok((Streaming("1c"), "ab")));
272/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("1c")), Ok((Streaming("1c"), "")));
273/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
274/// ```
275#[inline(always)]
276pub fn alpha0<T, E: ParseError<T>, const STREAMING: bool>(
277  input: T,
278) -> IResult<T, <T as IntoOutput>::Output, E>
279where
280  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
281  T: IntoOutput,
282  <T as InputTakeAtPosition>::Item: AsChar,
283{
284  if STREAMING {
285    streaming::alpha0(input)
286  } else {
287    complete::alpha0(input)
288  }
289}
290
291/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
292///
293/// *Complete version*: Will return an error if there's not enough input data,
294/// or the whole input if no terminating token is found  (a non alphabetic character).
295///
296/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
297/// or if no terminating token is found (a non alphabetic character).
298///
299/// # Example
300///
301/// ```
302/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
303/// # use nom8::character::alpha1;
304/// fn parser(input: &str) -> IResult<&str, &str> {
305///     alpha1(input)
306/// }
307///
308/// assert_eq!(parser("aB1c"), Ok(("1c", "aB")));
309/// assert_eq!(parser("1c"), Err(Err::Error(Error::new("1c", ErrorKind::Alpha))));
310/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Alpha))));
311/// ```
312///
313/// ```
314/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
315/// # use nom8::input::Streaming;
316/// # use nom8::character::alpha1;
317/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("aB1c")), Ok((Streaming("1c"), "aB")));
318/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("1c")), Err(Err::Error((Streaming("1c"), ErrorKind::Alpha))));
319/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
320/// ```
321#[inline(always)]
322pub fn alpha1<T, E: ParseError<T>, const STREAMING: bool>(
323  input: T,
324) -> IResult<T, <T as IntoOutput>::Output, E>
325where
326  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
327  T: IntoOutput,
328  <T as InputTakeAtPosition>::Item: AsChar,
329{
330  if STREAMING {
331    streaming::alpha1(input)
332  } else {
333    complete::alpha1(input)
334  }
335}
336
337/// Recognizes zero or more ASCII numerical characters: 0-9
338///
339/// *Complete version*: Will return an error if there's not enough input data,
340/// or the whole input if no terminating token is found (a non digit character).
341///
342/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
343/// or if no terminating token is found (a non digit character).
344///
345/// # Example
346///
347/// ```
348/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
349/// # use nom8::character::digit0;
350/// fn parser(input: &str) -> IResult<&str, &str> {
351///     digit0(input)
352/// }
353///
354/// assert_eq!(parser("21c"), Ok(("c", "21")));
355/// assert_eq!(parser("21"), Ok(("", "21")));
356/// assert_eq!(parser("a21c"), Ok(("a21c", "")));
357/// assert_eq!(parser(""), Ok(("", "")));
358/// ```
359///
360/// ```
361/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
362/// # use nom8::input::Streaming;
363/// # use nom8::character::digit0;
364/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("21c")), Ok((Streaming("c"), "21")));
365/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("a21c")), Ok((Streaming("a21c"), "")));
366/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
367/// ```
368#[inline(always)]
369pub fn digit0<T, E: ParseError<T>, const STREAMING: bool>(
370  input: T,
371) -> IResult<T, <T as IntoOutput>::Output, E>
372where
373  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
374  T: IntoOutput,
375  <T as InputTakeAtPosition>::Item: AsChar,
376{
377  if STREAMING {
378    streaming::digit0(input)
379  } else {
380    complete::digit0(input)
381  }
382}
383
384/// Recognizes one or more ASCII numerical characters: 0-9
385///
386/// *Complete version*: Will return an error if there's not enough input data,
387/// or the whole input if no terminating token is found (a non digit character).
388///
389/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
390/// or if no terminating token is found (a non digit character).
391///
392/// # Example
393///
394/// ```
395/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
396/// # use nom8::character::digit1;
397/// fn parser(input: &str) -> IResult<&str, &str> {
398///     digit1(input)
399/// }
400///
401/// assert_eq!(parser("21c"), Ok(("c", "21")));
402/// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit))));
403/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit))));
404/// ```
405///
406/// ```
407/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
408/// # use nom8::input::Streaming;
409/// # use nom8::character::digit1;
410/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("21c")), Ok((Streaming("c"), "21")));
411/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("c1")), Err(Err::Error((Streaming("c1"), ErrorKind::Digit))));
412/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
413/// ```
414///
415/// ## Parsing an integer
416///
417/// You can use `digit1` in combination with [`Parser::map_res`][crate::Parser::map_res] to parse an integer:
418///
419/// ```
420/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed, Parser};
421/// # use nom8::character::digit1;
422/// fn parser(input: &str) -> IResult<&str, u32> {
423///   digit1.map_res(str::parse).parse(input)
424/// }
425///
426/// assert_eq!(parser("416"), Ok(("", 416)));
427/// assert_eq!(parser("12b"), Ok(("b", 12)));
428/// assert!(parser("b").is_err());
429/// ```
430#[inline(always)]
431pub fn digit1<T, E: ParseError<T>, const STREAMING: bool>(
432  input: T,
433) -> IResult<T, <T as IntoOutput>::Output, E>
434where
435  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
436  T: IntoOutput,
437  <T as InputTakeAtPosition>::Item: AsChar,
438{
439  if STREAMING {
440    streaming::digit1(input)
441  } else {
442    complete::digit1(input)
443  }
444}
445
446/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
447///
448/// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character).
449///
450/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
451/// or if no terminating token is found (a non hexadecimal digit character).
452///
453/// # Example
454///
455/// ```
456/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
457/// # use nom8::character::hex_digit0;
458/// fn parser(input: &str) -> IResult<&str, &str> {
459///     hex_digit0(input)
460/// }
461///
462/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
463/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
464/// assert_eq!(parser(""), Ok(("", "")));
465/// ```
466///
467/// ```
468/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
469/// # use nom8::input::Streaming;
470/// # use nom8::character::hex_digit0;
471/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("Z"), "21c")));
472/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
473/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
474/// ```
475#[inline(always)]
476pub fn hex_digit0<T, E: ParseError<T>, const STREAMING: bool>(
477  input: T,
478) -> IResult<T, <T as IntoOutput>::Output, E>
479where
480  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
481  T: IntoOutput,
482  <T as InputTakeAtPosition>::Item: AsChar,
483{
484  if STREAMING {
485    streaming::hex_digit0(input)
486  } else {
487    complete::hex_digit0(input)
488  }
489}
490
491/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
492///
493/// *Complete version*: Will return an error if there's not enough input data,
494/// or the whole input if no terminating token is found (a non hexadecimal digit character).
495///
496/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
497/// or if no terminating token is found (a non hexadecimal digit character).
498///
499/// # Example
500///
501/// ```
502/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
503/// # use nom8::character::hex_digit1;
504/// fn parser(input: &str) -> IResult<&str, &str> {
505///     hex_digit1(input)
506/// }
507///
508/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
509/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::HexDigit))));
510/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::HexDigit))));
511/// ```
512///
513/// ```
514/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
515/// # use nom8::input::Streaming;
516/// # use nom8::character::hex_digit1;
517/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("Z"), "21c")));
518/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::HexDigit))));
519/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
520/// ```
521#[inline(always)]
522pub fn hex_digit1<T, E: ParseError<T>, const STREAMING: bool>(
523  input: T,
524) -> IResult<T, <T as IntoOutput>::Output, E>
525where
526  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
527  T: IntoOutput,
528  <T as InputTakeAtPosition>::Item: AsChar,
529{
530  if STREAMING {
531    streaming::hex_digit1(input)
532  } else {
533    complete::hex_digit1(input)
534  }
535}
536
537/// Recognizes zero or more octal characters: 0-7
538///
539/// *Complete version*: Will return the whole input if no terminating token is found (a non octal
540/// digit character).
541///
542/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
543/// or if no terminating token is found (a non octal digit character).
544///
545/// # Example
546///
547/// ```
548/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
549/// # use nom8::character::oct_digit0;
550/// fn parser(input: &str) -> IResult<&str, &str> {
551///     oct_digit0(input)
552/// }
553///
554/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
555/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
556/// assert_eq!(parser(""), Ok(("", "")));
557/// ```
558///
559/// ```
560/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
561/// # use nom8::input::Streaming;
562/// # use nom8::character::oct_digit0;
563/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("cZ"), "21")));
564/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
565/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
566/// ```
567#[inline(always)]
568pub fn oct_digit0<T, E: ParseError<T>, const STREAMING: bool>(
569  input: T,
570) -> IResult<T, <T as IntoOutput>::Output, E>
571where
572  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
573  T: IntoOutput,
574  <T as InputTakeAtPosition>::Item: AsChar,
575{
576  if STREAMING {
577    streaming::oct_digit0(input)
578  } else {
579    complete::oct_digit0(input)
580  }
581}
582
583/// Recognizes one or more octal characters: 0-7
584///
585/// *Complete version*: Will return an error if there's not enough input data,
586/// or the whole input if no terminating token is found (a non octal digit character).
587///
588/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
589/// or if no terminating token is found (a non octal digit character).
590///
591/// # Example
592///
593/// ```
594/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
595/// # use nom8::character::oct_digit1;
596/// fn parser(input: &str) -> IResult<&str, &str> {
597///     oct_digit1(input)
598/// }
599///
600/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
601/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::OctDigit))));
602/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OctDigit))));
603/// ```
604///
605/// ```
606/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
607/// # use nom8::input::Streaming;
608/// # use nom8::character::oct_digit1;
609/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("cZ"), "21")));
610/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::OctDigit))));
611/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
612/// ```
613#[inline(always)]
614pub fn oct_digit1<T, E: ParseError<T>, const STREAMING: bool>(
615  input: T,
616) -> IResult<T, <T as IntoOutput>::Output, E>
617where
618  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
619  T: IntoOutput,
620  <T as InputTakeAtPosition>::Item: AsChar,
621{
622  if STREAMING {
623    streaming::oct_digit1(input)
624  } else {
625    complete::oct_digit1(input)
626  }
627}
628
629/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
630///
631/// *Complete version*: Will return the whole input if no terminating token is found (a non
632/// alphanumerical character).
633///
634/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
635/// or if no terminating token is found (a non alphanumerical character).
636///
637/// # Example
638///
639/// ```
640/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
641/// # use nom8::character::alphanumeric0;
642/// fn parser(input: &str) -> IResult<&str, &str> {
643///     alphanumeric0(input)
644/// }
645///
646/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
647/// assert_eq!(parser("&Z21c"), Ok(("&Z21c", "")));
648/// assert_eq!(parser(""), Ok(("", "")));
649/// ```
650///
651/// ```
652/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
653/// # use nom8::input::Streaming;
654/// # use nom8::character::alphanumeric0;
655/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("21cZ%1")), Ok((Streaming("%1"), "21cZ")));
656/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("&Z21c")), Ok((Streaming("&Z21c"), "")));
657/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
658/// ```
659#[inline(always)]
660pub fn alphanumeric0<T, E: ParseError<T>, const STREAMING: bool>(
661  input: T,
662) -> IResult<T, <T as IntoOutput>::Output, E>
663where
664  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
665  T: IntoOutput,
666  <T as InputTakeAtPosition>::Item: AsChar,
667{
668  if STREAMING {
669    streaming::alphanumeric0(input)
670  } else {
671    complete::alphanumeric0(input)
672  }
673}
674
675/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
676///
677/// *Complete version*: Will return an error if there's not enough input data,
678/// or the whole input if no terminating token is found (a non alphanumerical character).
679///
680/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
681/// or if no terminating token is found (a non alphanumerical character).
682///
683/// # Example
684///
685/// ```
686/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
687/// # use nom8::character::alphanumeric1;
688/// fn parser(input: &str) -> IResult<&str, &str> {
689///     alphanumeric1(input)
690/// }
691///
692/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
693/// assert_eq!(parser("&H2"), Err(Err::Error(Error::new("&H2", ErrorKind::AlphaNumeric))));
694/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::AlphaNumeric))));
695/// ```
696///
697/// ```
698/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
699/// # use nom8::input::Streaming;
700/// # use nom8::character::alphanumeric1;
701/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("21cZ%1")), Ok((Streaming("%1"), "21cZ")));
702/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("&H2")), Err(Err::Error((Streaming("&H2"), ErrorKind::AlphaNumeric))));
703/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
704/// ```
705#[inline(always)]
706pub fn alphanumeric1<T, E: ParseError<T>, const STREAMING: bool>(
707  input: T,
708) -> IResult<T, <T as IntoOutput>::Output, E>
709where
710  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
711  T: IntoOutput,
712  <T as InputTakeAtPosition>::Item: AsChar,
713{
714  if STREAMING {
715    streaming::alphanumeric1(input)
716  } else {
717    complete::alphanumeric1(input)
718  }
719}
720
721/// Recognizes zero or more spaces and tabs.
722///
723/// *Complete version*: Will return the whole input if no terminating token is found (a non space
724/// character).
725///
726/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
727/// or if no terminating token is found (a non space character).
728///
729/// # Example
730///
731/// ```
732/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
733/// # use nom8::input::Streaming;
734/// # use nom8::character::space0;
735/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming(" \t21c")), Ok((Streaming("21c"), " \t")));
736/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
737/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
738/// ```
739#[inline(always)]
740pub fn space0<T, E: ParseError<T>, const STREAMING: bool>(
741  input: T,
742) -> IResult<T, <T as IntoOutput>::Output, E>
743where
744  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
745  T: IntoOutput,
746  <T as InputTakeAtPosition>::Item: AsChar + Clone,
747{
748  if STREAMING {
749    streaming::space0(input)
750  } else {
751    complete::space0(input)
752  }
753}
754
755/// Recognizes one or more spaces and tabs.
756///
757/// *Complete version*: Will return an error if there's not enough input data,
758/// or the whole input if no terminating token is found (a non space character).
759///
760/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
761/// or if no terminating token is found (a non space character).
762///
763/// # Example
764///
765/// ```
766/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
767/// # use nom8::character::space1;
768/// fn parser(input: &str) -> IResult<&str, &str> {
769///     space1(input)
770/// }
771///
772/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t")));
773/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::Space))));
774/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Space))));
775/// ```
776///
777/// ```
778/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
779/// # use nom8::input::Streaming;
780/// # use nom8::character::space1;
781/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming(" \t21c")), Ok((Streaming("21c"), " \t")));
782/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::Space))));
783/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
784/// ```
785#[inline(always)]
786pub fn space1<T, E: ParseError<T>, const STREAMING: bool>(
787  input: T,
788) -> IResult<T, <T as IntoOutput>::Output, E>
789where
790  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
791  T: IntoOutput,
792  <T as InputTakeAtPosition>::Item: AsChar + Clone,
793{
794  if STREAMING {
795    streaming::space1(input)
796  } else {
797    complete::space1(input)
798  }
799}
800
801/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
802///
803/// *Complete version*: will return the whole input if no terminating token is found (a non space
804/// character).
805///
806/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
807/// or if no terminating token is found (a non space character).
808///
809/// # Example
810///
811/// ```
812/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
813/// # use nom8::character::multispace0;
814/// fn parser(input: &str) -> IResult<&str, &str> {
815///     multispace0(input)
816/// }
817///
818/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
819/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
820/// assert_eq!(parser(""), Ok(("", "")));
821/// ```
822///
823/// ```
824/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
825/// # use nom8::input::Streaming;
826/// # use nom8::character::multispace0;
827/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming(" \t\n\r21c")), Ok((Streaming("21c"), " \t\n\r")));
828/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
829/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
830/// ```
831#[inline(always)]
832pub fn multispace0<T, E: ParseError<T>, const STREAMING: bool>(
833  input: T,
834) -> IResult<T, <T as IntoOutput>::Output, E>
835where
836  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
837  T: IntoOutput,
838  <T as InputTakeAtPosition>::Item: AsChar + Clone,
839{
840  if STREAMING {
841    streaming::multispace0(input)
842  } else {
843    complete::multispace0(input)
844  }
845}
846
847/// Recognizes one or more spaces, tabs, carriage returns and line feeds.
848///
849/// *Complete version*: will return an error if there's not enough input data,
850/// or the whole input if no terminating token is found (a non space character).
851///
852/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
853/// or if no terminating token is found (a non space character).
854///
855/// # Example
856///
857/// ```
858/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
859/// # use nom8::character::multispace1;
860/// fn parser(input: &str) -> IResult<&str, &str> {
861///     multispace1(input)
862/// }
863///
864/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
865/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::MultiSpace))));
866/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::MultiSpace))));
867/// ```
868///
869/// ```
870/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
871/// # use nom8::input::Streaming;
872/// # use nom8::character::multispace1;
873/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming(" \t\n\r21c")), Ok((Streaming("21c"), " \t\n\r")));
874/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::MultiSpace))));
875/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
876/// ```
877#[inline(always)]
878pub fn multispace1<T, E: ParseError<T>, const STREAMING: bool>(
879  input: T,
880) -> IResult<T, <T as IntoOutput>::Output, E>
881where
882  T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
883  T: IntoOutput,
884  <T as InputTakeAtPosition>::Item: AsChar + Clone,
885{
886  if STREAMING {
887    streaming::multispace1(input)
888  } else {
889    complete::multispace1(input)
890  }
891}
892
893#[doc(hidden)]
894macro_rules! ints {
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        ///
901        /// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
902        #[inline(always)]
903        pub fn $t<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, $t, E>
904            where
905            T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputTake + Clone + InputIsStreaming<STREAMING>,
906            T: IntoOutput,
907            <T as InputIter>::Item: AsChar,
908            T: for <'a> Compare<&'a[u8]>,
909            {
910                if STREAMING {
911                  streaming::$t(input)
912                } else {
913                  complete::$t(input)
914                }
915            }
916        )+
917    }
918}
919
920ints! { i8 i16 i32 i64 i128 }
921
922#[doc(hidden)]
923macro_rules! uints {
924    ($($t:tt)+) => {
925        $(
926        /// will parse a number in text form to a number
927        ///
928        /// *Complete version*: can parse until the end of input.
929        ///
930        /// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
931        #[inline(always)]
932        pub fn $t<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, $t, E>
933            where
934            T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputIsStreaming<STREAMING>,
935            T: IntoOutput,
936            <T as InputIter>::Item: AsChar,
937            {
938                if STREAMING {
939                  streaming::$t(input)
940                } else {
941                  complete::$t(input)
942                }
943            }
944        )+
945    }
946}
947
948uints! { u8 u16 u32 u64 u128 }
949
950/// Recognizes floating point number in text format and returns a f32.
951///
952/// *Complete version*: Can parse until the end of input.
953///
954/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
955///
956/// # Example
957///
958/// ```rust
959/// # use nom8::{Err, error::ErrorKind, Needed};
960/// # use nom8::Needed::Size;
961/// use nom8::character::f32;
962///
963/// let parser = |s| {
964///   f32(s)
965/// };
966///
967/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
968/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
969/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
970/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
971/// ```
972///
973/// ```rust
974/// # use nom8::{Err, error::ErrorKind, Needed};
975/// # use nom8::Needed::Size;
976/// # use nom8::input::Streaming;
977/// use nom8::character::f32;
978///
979/// let parser = |s| {
980///   f32(s)
981/// };
982///
983/// assert_eq!(parser(Streaming("11e-1 ")), Ok((Streaming(" "), 1.1)));
984/// assert_eq!(parser(Streaming("11e-1")), Err(Err::Incomplete(Needed::new(1))));
985/// assert_eq!(parser(Streaming("123E-02")), Err(Err::Incomplete(Needed::new(1))));
986/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), 123.0)));
987/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Float))));
988/// ```
989#[inline(always)]
990pub fn f32<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, f32, E>
991where
992  T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
993  T: Clone + Offset + Compare<&'static str>,
994  T: InputIter + InputLength + InputTake + InputIsStreaming<STREAMING>,
995  T: IntoOutput,
996  <T as IntoOutput>::Output: ParseTo<f32>,
997  <T as InputIter>::Item: AsChar + Copy,
998  <T as InputIter>::IterElem: Clone,
999  T: InputTakeAtPosition,
1000  <T as InputTakeAtPosition>::Item: AsChar,
1001  T: AsBytes,
1002  T: for<'a> Compare<&'a [u8]>,
1003{
1004  if STREAMING {
1005    crate::number::streaming::float(input)
1006  } else {
1007    crate::number::complete::float(input)
1008  }
1009}
1010
1011/// Recognizes floating point number in text format and returns a f64.
1012///
1013/// *Complete version*: Can parse until the end of input.
1014///
1015/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
1016///
1017/// # Example
1018///
1019/// ```rust
1020/// # use nom8::{Err, error::ErrorKind, Needed};
1021/// # use nom8::Needed::Size;
1022/// use nom8::character::f64;
1023///
1024/// let parser = |s| {
1025///   f64(s)
1026/// };
1027///
1028/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
1029/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
1030/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
1031/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
1032/// ```
1033///
1034/// ```rust
1035/// # use nom8::{Err, error::ErrorKind, Needed};
1036/// # use nom8::Needed::Size;
1037/// # use nom8::input::Streaming;
1038/// use nom8::character::f64;
1039///
1040/// let parser = |s| {
1041///   f64(s)
1042/// };
1043///
1044/// assert_eq!(parser(Streaming("11e-1 ")), Ok((Streaming(" "), 1.1)));
1045/// assert_eq!(parser(Streaming("11e-1")), Err(Err::Incomplete(Needed::new(1))));
1046/// assert_eq!(parser(Streaming("123E-02")), Err(Err::Incomplete(Needed::new(1))));
1047/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), 123.0)));
1048/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Float))));
1049/// ```
1050#[inline(always)]
1051pub fn f64<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, f64, E>
1052where
1053  T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
1054  T: Clone + Offset + Compare<&'static str>,
1055  T: InputIter + InputLength + InputTake + InputIsStreaming<STREAMING>,
1056  T: IntoOutput,
1057  <T as IntoOutput>::Output: ParseTo<f64>,
1058  <T as InputIter>::Item: AsChar + Copy,
1059  <T as InputIter>::IterElem: Clone,
1060  T: InputTakeAtPosition,
1061  <T as InputTakeAtPosition>::Item: AsChar,
1062  T: AsBytes,
1063  T: for<'a> Compare<&'a [u8]>,
1064{
1065  if STREAMING {
1066    crate::number::streaming::double(input)
1067  } else {
1068    crate::number::complete::double(input)
1069  }
1070}
1071
1072/// Recognizes floating point number in a byte string and returns the corresponding slice.
1073///
1074/// *Complete version*: Can parse until the end of input.
1075///
1076/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
1077///
1078/// # Example
1079///
1080/// ```rust
1081/// # use nom8::{Err, error::ErrorKind, Needed};
1082/// # use nom8::Needed::Size;
1083/// use nom8::character::recognize_float;
1084///
1085/// let parser = |s| {
1086///   recognize_float(s)
1087/// };
1088///
1089/// assert_eq!(parser("11e-1"), Ok(("", "11e-1")));
1090/// assert_eq!(parser("123E-02"), Ok(("", "123E-02")));
1091/// assert_eq!(parser("123K-01"), Ok(("K-01", "123")));
1092/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char))));
1093/// ```
1094///
1095/// ```rust
1096/// # use nom8::{Err, error::ErrorKind, Needed};
1097/// # use nom8::input::Streaming;
1098/// use nom8::character::recognize_float;
1099///
1100/// let parser = |s| {
1101///   recognize_float(s)
1102/// };
1103///
1104/// assert_eq!(parser(Streaming("11e-1;")), Ok((Streaming(";"), "11e-1")));
1105/// assert_eq!(parser(Streaming("123E-02;")), Ok((Streaming(";"), "123E-02")));
1106/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), "123")));
1107/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Char))));
1108/// ```
1109#[inline(always)]
1110pub fn recognize_float<T, E: ParseError<T>, const STREAMING: bool>(
1111  input: T,
1112) -> IResult<T, <T as IntoOutput>::Output, E>
1113where
1114  T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
1115  T: Clone + Offset,
1116  T: InputIter + InputLength + InputIsStreaming<STREAMING>,
1117  T: IntoOutput,
1118  <T as InputIter>::Item: AsChar,
1119  T: InputTakeAtPosition,
1120  <T as InputTakeAtPosition>::Item: AsChar,
1121{
1122  if STREAMING {
1123    crate::number::streaming::recognize_float(input)
1124  } else {
1125    crate::number::complete::recognize_float(input)
1126  }
1127}
1128
1129/// Recognizes a floating point number in text format
1130///
1131/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
1132/// data.
1133///
1134/// *Complete version*: Can parse until the end of input.
1135///
1136/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
1137///
1138#[inline(always)]
1139pub fn recognize_float_parts<T, E: ParseError<T>, const STREAMING: bool>(
1140  input: T,
1141) -> IResult<
1142  T,
1143  (
1144    bool,
1145    <T as IntoOutput>::Output,
1146    <T as IntoOutput>::Output,
1147    i32,
1148  ),
1149  E,
1150>
1151where
1152  T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
1153  T: Clone + Offset,
1154  T: InputIter + InputTake + InputIsStreaming<STREAMING>,
1155  T: IntoOutput,
1156  <T as InputIter>::Item: AsChar + Copy,
1157  T: InputTakeAtPosition + InputLength,
1158  <T as InputTakeAtPosition>::Item: AsChar,
1159  T: for<'a> Compare<&'a [u8]>,
1160  T: AsBytes,
1161{
1162  if STREAMING {
1163    crate::number::streaming::recognize_float_parts(input)
1164  } else {
1165    crate::number::complete::recognize_float_parts(input)
1166  }
1167}
1168
1169#[inline]
1170#[doc(hidden)]
1171#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")]
1172pub fn is_alphabetic(chr: u8) -> bool {
1173  (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A)
1174}
1175
1176#[inline]
1177#[doc(hidden)]
1178#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")]
1179pub fn is_digit(chr: u8) -> bool {
1180  chr >= 0x30 && chr <= 0x39
1181}
1182
1183#[inline]
1184#[doc(hidden)]
1185#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")]
1186pub fn is_hex_digit(chr: u8) -> bool {
1187  (chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66)
1188}
1189
1190#[inline]
1191#[doc(hidden)]
1192#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")]
1193pub fn is_oct_digit(chr: u8) -> bool {
1194  chr >= 0x30 && chr <= 0x37
1195}
1196
1197#[inline]
1198#[doc(hidden)]
1199#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")]
1200pub fn is_alphanumeric(chr: u8) -> bool {
1201  #![allow(deprecated)]
1202  is_alphabetic(chr) || is_digit(chr)
1203}
1204
1205#[inline]
1206#[doc(hidden)]
1207#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_space`")]
1208pub fn is_space(chr: u8) -> bool {
1209  chr == b' ' || chr == b'\t'
1210}
1211
1212#[inline]
1213#[doc(hidden)]
1214#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_newline`")]
1215pub fn is_newline(chr: u8) -> bool {
1216  chr == b'\n'
1217}