/// Mark a value as case-insensitive for ASCII characters /// /// # Example /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::Caseless; /// /// fn parser<'s>(s: &mut &'s str) -> ModalResult<&'s str> { /// Caseless("hello").parse_next(s) /// } /// /// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello"))); /// assert_eq!(parser.parse_peek("hello, World!"), Ok((", World!", "hello"))); /// assert_eq!(parser.parse_peek("HeLlo, World!"), Ok((", World!", "HeLlo"))); /// assert!(parser.parse_peek("Some").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` #[derive(Copy, Clone, Debug)] pubstruct Caseless<T>(pub T);
impl Caseless<&str> { /// Get the byte-representation of this case-insensitive value #[inline(always)] pubfn as_bytes(&self) -> Caseless<&[u8]> {
Caseless(self.0.as_bytes())
}
}
/// Recognizes the string `"\r\n"`. /// /// *Complete version*: Will return an error if there's not enough input data. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn crlf<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::crlf.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::crlf; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// crlf.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("\r\nc"), Ok(("c", "\r\n"))); /// assert!(parser.parse_peek("ab\r\nc").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::crlf; /// assert_eq!(crlf::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\r\nc")), Ok((Partial::new("c"), "\r\n"))); /// assert!(crlf::<_, ErrMode<ContextError>>.parse_peek(Partial::new("ab\r\nc")).is_err()); /// assert_eq!(crlf::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::Unknown))); /// ``` #[inline(always)] pubfn crlf<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream + Compare<&'static str>,
Error: ParserError<Input>,
{
trace("crlf", "\r\n").parse_next(input)
}
/// Recognizes a string of 0+ characters until `"\r\n"`, `"\n"`, or eof. /// /// *Complete version*: Will return an error if there's not enough input data. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn till_line_ending<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::till_line_ending.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::till_line_ending; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// till_line_ending.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("ab\r\nc"), Ok(("\r\nc", "ab"))); /// assert_eq!(parser.parse_peek("ab\nc"), Ok(("\nc", "ab"))); /// assert_eq!(parser.parse_peek("abc"), Ok(("", "abc"))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// assert!(parser.parse_peek("a\rb\nc").is_err()); /// assert!(parser.parse_peek("a\rbc").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::till_line_ending; /// assert_eq!(till_line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("ab\r\nc")), Ok((Partial::new("\r\nc"), "ab"))); /// assert_eq!(till_line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("abc")), Err(ErrMode::Incomplete(Needed::Unknown))); /// assert_eq!(till_line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::Unknown))); /// assert!(till_line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("a\rb\nc")).is_err()); /// assert!(till_line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("a\rbc")).is_err()); /// ``` #[inline(always)] pubfn till_line_ending<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream + Compare<&'static str> + FindSlice<(char, char)>,
<Input as Stream>::Token: AsChar + Clone,
Error: ParserError<Input>,
{
trace("till_line_ending", move |input: &mut Input| { if <Input as StreamIsPartial>::is_partial_supported() {
till_line_ending_::<_, _, true>(input)
} else {
till_line_ending_::<_, _, false>(input)
}
})
.parse_next(input)
}
fn till_line_ending_<I, E: ParserError<I>, const PARTIAL: bool>(
input: &mut I,
) -> Result<<I as Stream>::Slice, E> where
I: StreamIsPartial,
I: Stream,
I: Compare<&'static str>,
I: FindSlice<(char, char)>,
<I as Stream>::Token: AsChar + Clone,
{ let res = match take_until(0.., ('\r', '\n'))
.parse_next(input)
.map_err(|e: E| e)
{
Ok(slice) => slice,
Err(err) if err.is_backtrack() => input.finish(),
Err(err) => { return Err(err);
}
}; if matches!(input.compare("\r"), CompareResult::Ok(_)) { let comp = input.compare("\r\n"); match comp {
CompareResult::Ok(_) => {}
CompareResult::Incomplete if PARTIAL && input.is_partial() => { return Err(ParserError::incomplete(input, Needed::Unknown));
}
CompareResult::Incomplete | CompareResult::Error => { return Err(ParserError::from_input(input));
}
}
}
Ok(res)
}
/// Recognizes an end of line (both `"\n"` and `"\r\n"`). /// /// *Complete version*: Will return an error if there's not enough input data. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn line_ending<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::line_ending.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::line_ending; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// line_ending.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("\r\nc"), Ok(("c", "\r\n"))); /// assert!(parser.parse_peek("ab\r\nc").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::line_ending; /// assert_eq!(line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\r\nc")), Ok((Partial::new("c"), "\r\n"))); /// assert!(line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("ab\r\nc")).is_err()); /// assert_eq!(line_ending::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::Unknown))); /// ``` #[inline(always)] pubfn line_ending<Input, Error>(input: &mut Input) -> Result<<Input asStream>::Slice, Error> where
Input: StreamIsPartial + Stream + Compare<&'static str>,
Error: ParserError<Input>,
{
trace("line_ending", alt(("\n", "\r\n"))).parse_next(input)
}
/// Matches a newline character `'\n'`. /// /// *Complete version*: Will return an error if there's not enough input data. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn newline(input: &mut &str) -> ModalResult<char> /// # { /// # winnow::ascii::newline.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::newline; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<char> { /// newline.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("\nc"), Ok(("c", '\n'))); /// assert!(parser.parse_peek("\r\nc").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::newline; /// assert_eq!(newline::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\nc")), Ok((Partial::new("c"), '\n'))); /// assert!(newline::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\r\nc")).is_err()); /// assert_eq!(newline::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::Unknown))); /// ``` #[inline(always)] pubfn newline<I, Error: ParserError<I>>(input: &mut I) -> Result<char, Error> where
I: StreamIsPartial,
I: Stream,
I: Compare<char>,
{
trace("newline", '\n').parse_next(input)
}
/// Matches a tab character `'\t'`. /// /// *Complete version*: Will return an error if there's not enough input data. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn tab(input: &mut &str) -> ModalResult<char> /// # { /// # winnow::ascii::tab.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::tab; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<char> { /// tab.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("\tc"), Ok(("c", '\t'))); /// assert!(parser.parse_peek("\r\nc").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::tab; /// assert_eq!(tab::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\tc")), Ok((Partial::new("c"), '\t'))); /// assert!(tab::<_, ErrMode<ContextError>>.parse_peek(Partial::new("\r\nc")).is_err()); /// assert_eq!(tab::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::Unknown))); /// ``` #[inline(always)] pubfn tab<Input, Error>(input: &mut Input) -> Result<char, Error> where
Input: StreamIsPartial + Stream + Compare<char>,
Error: ParserError<Input>,
{
trace("tab", '\t').parse_next(input)
}
/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: `'a'..='z'`, `'A'..='Z'` /// /// *Complete version*: Will return the whole input if no terminating token is found (a non /// alphabetic character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non alphabetic character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn alpha0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::alpha0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::alpha0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// alpha0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("ab1c"), Ok(("1c", "ab"))); /// assert_eq!(parser.parse_peek("1c"), Ok(("1c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::alpha0; /// assert_eq!(alpha0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("ab1c")), Ok((Partial::new("1c"), "ab"))); /// assert_eq!(alpha0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("1c")), Ok((Partial::new("1c"), ""))); /// assert_eq!(alpha0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn alpha0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("alpha0", take_while(0.., AsChar::is_alpha)).parse_next(input)
}
/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: `'a'..='z'`, `'A'..='Z'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non alphabetic character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non alphabetic character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn alpha1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::alpha1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::alpha1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// alpha1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("aB1c"), Ok(("1c", "aB"))); /// assert!(parser.parse_peek("1c").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::alpha1; /// assert_eq!(alpha1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("aB1c")), Ok((Partial::new("1c"), "aB"))); /// assert!(alpha1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("1c")).is_err()); /// assert_eq!(alpha1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn alpha1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("alpha1", take_while(1.., AsChar::is_alpha)).parse_next(input)
}
/// Recognizes zero or more ASCII numerical characters: `'0'..='9'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn digit0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::digit0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::digit0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// digit0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21c"), Ok(("c", "21"))); /// assert_eq!(parser.parse_peek("21"), Ok(("", "21"))); /// assert_eq!(parser.parse_peek("a21c"), Ok(("a21c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::digit0; /// assert_eq!(digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21c")), Ok((Partial::new("c"), "21"))); /// assert_eq!(digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("a21c")), Ok((Partial::new("a21c"), ""))); /// assert_eq!(digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn digit0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("digit0", take_while(0.., AsChar::is_dec_digit)).parse_next(input)
}
/// Recognizes one or more ASCII numerical characters: `'0'..='9'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn digit1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::digit1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::digit1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// digit1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21c"), Ok(("c", "21"))); /// assert!(parser.parse_peek("c1").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::digit1; /// assert_eq!(digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21c")), Ok((Partial::new("c"), "21"))); /// assert!(digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("c1")).is_err()); /// assert_eq!(digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` /// /// ## Parsing an integer /// /// You can use `digit1` in combination with [`Parser::try_map`] to parse an integer: /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::digit1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<u32> { /// digit1.try_map(str::parse).parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("416"), Ok(("", 416))); /// assert_eq!(parser.parse_peek("12b"), Ok(("b", 12))); /// assert!(parser.parse_peek("b").is_err()); /// ``` #[inline(always)] pubfn digit1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("digit1", take_while(1.., AsChar::is_dec_digit)).parse_next(input)
}
/// Recognizes zero or more ASCII hexadecimal numerical characters: `'0'..='9'`, `'A'..='F'`, /// `'a'..='f'` /// /// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non hexadecimal digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn hex_digit0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::hex_digit0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::hex_digit0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// hex_digit0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ"), Ok(("Z", "21c"))); /// assert_eq!(parser.parse_peek("Z21c"), Ok(("Z21c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::hex_digit0; /// assert_eq!(hex_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ")), Ok((Partial::new("Z"), "21c"))); /// assert_eq!(hex_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("Z21c")), Ok((Partial::new("Z21c"), ""))); /// assert_eq!(hex_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn hex_digit0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("hex_digit0", take_while(0.., AsChar::is_hex_digit)).parse_next(input)
}
/// Recognizes one or more ASCII hexadecimal numerical characters: `'0'..='9'`, `'A'..='F'`, /// `'a'..='f'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non hexadecimal digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non hexadecimal digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn hex_digit1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::hex_digit1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::hex_digit1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// hex_digit1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ"), Ok(("Z", "21c"))); /// assert!(parser.parse_peek("H2").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::hex_digit1; /// assert_eq!(hex_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ")), Ok((Partial::new("Z"), "21c"))); /// assert!(hex_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("H2")).is_err()); /// assert_eq!(hex_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn hex_digit1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("hex_digit1", take_while(1.., AsChar::is_hex_digit)).parse_next(input)
}
/// Recognizes zero or more octal characters: `'0'..='7'` /// /// *Complete version*: Will return the whole input if no terminating token is found (a non octal /// digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non octal digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn oct_digit0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::oct_digit0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::oct_digit0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// oct_digit0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ"), Ok(("cZ", "21"))); /// assert_eq!(parser.parse_peek("Z21c"), Ok(("Z21c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::oct_digit0; /// assert_eq!(oct_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ")), Ok((Partial::new("cZ"), "21"))); /// assert_eq!(oct_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("Z21c")), Ok((Partial::new("Z21c"), ""))); /// assert_eq!(oct_digit0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn oct_digit0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial,
Input: Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("oct_digit0", take_while(0.., AsChar::is_oct_digit)).parse_next(input)
}
/// Recognizes one or more octal characters: `'0'..='7'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non octal digit character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non octal digit character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn oct_digit1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::oct_digit1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::oct_digit1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// oct_digit1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ"), Ok(("cZ", "21"))); /// assert!(parser.parse_peek("H2").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::oct_digit1; /// assert_eq!(oct_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ")), Ok((Partial::new("cZ"), "21"))); /// assert!(oct_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("H2")).is_err()); /// assert_eq!(oct_digit1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn oct_digit1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("oct_digit0", take_while(1.., AsChar::is_oct_digit)).parse_next(input)
}
/// Recognizes zero or more ASCII numerical and alphabetic characters: `'a'..='z'`, `'A'..='Z'`, `'0'..='9'` /// /// *Complete version*: Will return the whole input if no terminating token is found (a non /// alphanumerical character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non alphanumerical character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn alphanumeric0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::alphanumeric0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::alphanumeric0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// alphanumeric0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ%1"), Ok(("%1", "21cZ"))); /// assert_eq!(parser.parse_peek("&Z21c"), Ok(("&Z21c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::alphanumeric0; /// assert_eq!(alphanumeric0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ%1")), Ok((Partial::new("%1"), "21cZ"))); /// assert_eq!(alphanumeric0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("&Z21c")), Ok((Partial::new("&Z21c"), ""))); /// assert_eq!(alphanumeric0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn alphanumeric0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("alphanumeric0", take_while(0.., AsChar::is_alphanum)).parse_next(input)
}
/// Recognizes one or more ASCII numerical and alphabetic characters: `'a'..='z'`, `'A'..='Z'`, `'0'..='9'` /// /// *Complete version*: Will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non alphanumerical character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non alphanumerical character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn alphanumeric1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::alphanumeric1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::alphanumeric1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// alphanumeric1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek("21cZ%1"), Ok(("%1", "21cZ"))); /// assert!(parser.parse_peek("&H2").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::alphanumeric1; /// assert_eq!(alphanumeric1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("21cZ%1")), Ok((Partial::new("%1"), "21cZ"))); /// assert!(alphanumeric1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("&H2")).is_err()); /// assert_eq!(alphanumeric1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn alphanumeric1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("alphanumeric1", take_while(1.., AsChar::is_alphanum)).parse_next(input)
}
/// Recognizes zero or more spaces and tabs. /// /// *Complete version*: Will return the whole input if no terminating token is found (a non space /// character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non space character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn space0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::space0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::space0; /// assert_eq!(space0::<_, ErrMode<ContextError>>.parse_peek(Partial::new(" \t21c")), Ok((Partial::new("21c"), " \t"))); /// assert_eq!(space0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("Z21c")), Ok((Partial::new("Z21c"), ""))); /// assert_eq!(space0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn space0<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("space0", take_while(0.., AsChar::is_space)).parse_next(input)
}
/// Recognizes one or more spaces and tabs. /// /// *Complete version*: Will return the whole input if no terminating token is found (a non space /// character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non space character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn space1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::space1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::space1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// space1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek(" \t21c"), Ok(("21c", " \t"))); /// assert!(parser.parse_peek("H2").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::space1; /// assert_eq!(space1::<_, ErrMode<ContextError>>.parse_peek(Partial::new(" \t21c")), Ok((Partial::new("21c"), " \t"))); /// assert!(space1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("H2")).is_err()); /// assert_eq!(space1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn space1<Input, Error>(input: &mut Input) -> Result<<Input as Stream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
Error: ParserError<Input>,
{
trace("space1", take_while(1.., AsChar::is_space)).parse_next(input)
}
/// Recognizes zero or more spaces, tabs, carriage returns and line feeds. /// /// *Complete version*: will return the whole input if no terminating token is found (a non space /// character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non space character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn multispace0<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::multispace0.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::multispace0; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// multispace0.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); /// assert_eq!(parser.parse_peek("Z21c"), Ok(("Z21c", ""))); /// assert_eq!(parser.parse_peek(""), Ok(("", ""))); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::multispace0; /// assert_eq!(multispace0::<_, ErrMode<ContextError>>.parse_peek(Partial::new(" \t\n\r21c")), Ok((Partial::new("21c"), " \t\n\r"))); /// assert_eq!(multispace0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("Z21c")), Ok((Partial::new("Z21c"), ""))); /// assert_eq!(multispace0::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn multispace0<Input, Error>(input: &mut Input) -> Result<<Input asStream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar + Clone,
Error: ParserError<Input>,
{
trace("multispace0", take_while(0.., (' ', '\t', '\r', '\n'))).parse_next(input)
}
/// Recognizes one or more spaces, tabs, carriage returns and line feeds. /// /// *Complete version*: will return an error if there's not enough input data, /// or the whole input if no terminating token is found (a non space character). /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data, /// or if no terminating token is found (a non space character). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream]: /// ```rust /// # use winnow::prelude::*;; /// pub fn multispace1<'i>(input: &mut &'i str) -> ModalResult<&'i str> /// # { /// # winnow::ascii::multispace1.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::ascii::multispace1; /// fn parser<'s>(input: &mut &'s str) -> ModalResult<&'s str> { /// multispace1.parse_next(input) /// } /// /// assert_eq!(parser.parse_peek(" \t\n\r21c"), Ok(("21c", " \t\n\r"))); /// assert!(parser.parse_peek("H2").is_err()); /// assert!(parser.parse_peek("").is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::ContextError, error::Needed}; /// # use winnow::Partial; /// # use winnow::ascii::multispace1; /// assert_eq!(multispace1::<_, ErrMode<ContextError>>.parse_peek(Partial::new(" \t\n\r21c")), Ok((Partial::new("21c"), " \t\n\r"))); /// assert!(multispace1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("H2")).is_err()); /// assert_eq!(multispace1::<_, ErrMode<ContextError>>.parse_peek(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1)))); /// ``` #[inline(always)] pubfn multispace1<Input, Error>(input: &mut Input) -> Result<<Input asStream>::Slice, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar + Clone,
Error: ParserError<Input>,
{
trace("multispace1", take_while(1.., (' ', '\t', '\r', '\n'))).parse_next(input)
}
/// Decode a decimal unsigned integer (e.g. [`u32`]) /// /// *Complete version*: can parse until the end of input. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream] into a `u32`: /// ```rust /// # use winnow::prelude::*;; /// pub fn dec_uint(input: &mut &str) -> ModalResult<u32> /// # { /// # winnow::ascii::dec_uint.parse_next(input) /// # } /// ``` #[doc(alias = "u8")] #[doc(alias = "u16")] #[doc(alias = "u32")] #[doc(alias = "u64")] #[doc(alias = "u128")] pubfn dec_uint<Input, Output, Error>(input: &mut Input) -> Result<Output, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Slice: AsBStr,
<Input as Stream>::Token: AsChar + Clone,
Output: Uint,
Error: ParserError<Input>,
{
trace("dec_uint", move |input: &mut Input| {
alt(((one_of('1'..='9'), digit0).void(), one_of('0').void()))
.take()
.verify_map(|s: <Input as Stream>::Slice| { let s = s.as_bstr(); // SAFETY: Only 7-bit ASCII characters are parsed let s = unsafe { crate::lib::std::str::from_utf8_unchecked(s) };
Output::try_from_dec_uint(s)
})
.parse_next(input)
})
.parse_next(input)
}
/// Metadata for parsing unsigned integers, see [`dec_uint`] pubtrait Uint: Sized { #[doc(hidden)] fn try_from_dec_uint(slice: &str) -> Option<Self>;
}
/// Decode a decimal signed integer (e.g. [`i32`]) /// /// *Complete version*: can parse until the end of input. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if there's not enough input data. /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream] into an `i32`: /// ```rust /// # use winnow::prelude::*;; /// pub fn dec_int(input: &mut &str) -> ModalResult<i32> /// # { /// # winnow::ascii::dec_int.parse_next(input) /// # } /// ``` #[doc(alias = "i8")] #[doc(alias = "i16")] #[doc(alias = "i32")] #[doc(alias = "i64")] #[doc(alias = "i128")] pubfn dec_int<Input, Output, Error>(input: &mut Input) -> Result<Output, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Slice: AsBStr,
<Input as Stream>::Token: AsChar + Clone,
Output: Int,
Error: ParserError<Input>,
{
trace("dec_int", move |input: &mut Input| { let sign = opt(dispatch! {any.map(AsChar::as_char); '+' => empty.value(true), '-' => empty.value(false),
_ => fail,
});
alt(((sign, one_of('1'..='9'), digit0).void(), one_of('0').void()))
.take()
.verify_map(|s: <Input as Stream>::Slice| { let s = s.as_bstr(); // SAFETY: Only 7-bit ASCII characters are parsed let s = unsafe { crate::lib::std::str::from_utf8_unchecked(s) };
Output::try_from_dec_int(s)
})
.parse_next(input)
})
.parse_next(input)
}
/// Metadata for parsing signed integers, see [`dec_int`] pubtrait Int: Sized { #[doc(hidden)] fn try_from_dec_int(slice: &str) -> Option<Self>;
}
impl Int for i8 { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
impl Int for i16 { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
impl Int for i32 { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
impl Int for i64 { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
impl Int for i128 { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
impl Int for isize { fn try_from_dec_int(slice: &str) -> Option<Self> {
slice.parse().ok()
}
}
/// Decode a variable-width hexadecimal integer (e.g. [`u32`]) /// /// *Complete version*: Will parse until the end of input if it has fewer characters than the type /// supports. /// /// *[Partial version][crate::_topic::partial]*: Will return `Err(winnow::error::ErrMode::Incomplete(_))` if end-of-input /// is hit before a hard boundary (non-hex character, more characters than supported). /// /// # Effective Signature /// /// Assuming you are parsing a `&str` [Stream] into a `u32`: /// ```rust /// # use winnow::prelude::*;; /// pub fn hex_uint(input: &mut &str) -> ModalResult<u32> /// # { /// # winnow::ascii::hex_uint.parse_next(input) /// # } /// ``` /// /// # Example /// /// ```rust /// # use winnow::prelude::*; /// use winnow::ascii::hex_uint; /// /// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<u32> { /// hex_uint(s) /// } /// /// assert_eq!(parser.parse_peek(&b"01AE"[..]), Ok((&b""[..], 0x01AE))); /// assert_eq!(parser.parse_peek(&b"abc"[..]), Ok((&b""[..], 0x0ABC))); /// assert!(parser.parse_peek(&b"ggg"[..]).is_err()); /// ``` /// /// ```rust /// # use winnow::prelude::*; /// # use winnow::{error::ErrMode, error::Needed}; /// # use winnow::Partial; /// use winnow::ascii::hex_uint; /// /// fn parser<'s>(s: &mut Partial<&'s [u8]>) -> ModalResult<u32> { /// hex_uint(s) /// } /// /// assert_eq!(parser.parse_peek(Partial::new(&b"01AE;"[..])), Ok((Partial::new(&b";"[..]), 0x01AE))); /// assert_eq!(parser.parse_peek(Partial::new(&b"abc"[..])), Err(ErrMode::Incomplete(Needed::new(1)))); /// assert!(parser.parse_peek(Partial::new(&b"ggg"[..])).is_err()); /// ``` #[inline] pubfn hex_uint<Input, Output, Error>(input: &mut Input) -> Result<Output, Error> where
Input: StreamIsPartial + Stream,
<Input as Stream>::Token: AsChar,
<Input as Stream>::Slice: AsBStr,
Output: HexUint,
Error: ParserError<Input>,
{
trace("hex_uint", move |input: &mut Input| { let invalid_offset = input
.offset_for(|c| { let c = c.as_char();
!"0123456789abcdefABCDEF".contains(c)
})
.unwrap_or_else(|| input.eof_offset()); let max_nibbles = Output::max_nibbles(sealed::SealedMarker); let max_offset = input.offset_at(max_nibbles); let offset = match max_offset {
Ok(max_offset) => { if max_offset < invalid_offset { // Overflow return Err(ParserError::from_input(input));
} else {
invalid_offset
}
}
Err(_) => { if <Input as StreamIsPartial>::is_partial_supported()
&& input.is_partial()
&& invalid_offset == input.eof_offset()
{ // Only the next byte is guaranteed required return Err(ParserError::incomplete(input, Needed::new(1)));
} else {
invalid_offset
}
}
}; if offset == 0 { // Must be at least one digit return Err(ParserError::from_input(input));
} let parsed = input.next_slice(offset);
letmut res = Output::default(); for c in parsed.as_bstr() { let nibble = *c as char; let nibble = nibble.to_digit(16).unwrap_or(0) as u8; let nibble = Output::from(nibble);
res = (res << Output::from(4)) + nibble;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.