Source code

Revision control

Copy as Markdown

Other Tools

//! Basic types to build the parsers
use crate::ascii::Caseless as AsciiCaseless;
use crate::combinator::impls;
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
use crate::error::FromRecoverableError;
use crate::error::{AddContext, FromExternalError, ParseError, ParserError, Result};
use crate::stream::{Compare, Location, ParseSlice, Stream, StreamIsPartial};
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
use crate::stream::{Recover, Recoverable};
/// Core trait for parsing
///
/// The simplest way to implement a `Parser` is with a function
/// ```rust
/// use winnow::prelude::*;
///
/// fn empty(input: &mut &str) -> ModalResult<()> {
/// let output = ();
/// Ok(output)
/// }
///
/// let (input, output) = empty.parse_peek("Hello").unwrap();
/// assert_eq!(input, "Hello"); // We didn't consume any input
/// ```
///
/// which can be made stateful by returning a function
/// ```rust
/// use winnow::prelude::*;
///
/// fn empty<O: Clone>(output: O) -> impl FnMut(&mut &str) -> ModalResult<O> {
/// move |input: &mut &str| {
/// let output = output.clone();
/// Ok(output)
/// }
/// }
///
/// let (input, output) = empty("World").parse_peek("Hello").unwrap();
/// assert_eq!(input, "Hello"); // We didn't consume any input
/// assert_eq!(output, "World");
/// ```
///
/// Additionally, some basic types implement `Parser` as well, including
/// - `u8` and `char`, see [`winnow::token::one_of`][crate::token::one_of]
/// - `&[u8]` and `&str`, see [`winnow::token::literal`][crate::token::literal]
pub trait Parser<I, O, E> {
/// Parse all of `input`, generating `O` from it
#[inline]
fn parse(&mut self, mut input: I) -> Result<O, ParseError<I, <E as ParserError<I>>::Inner>>
where
Self: core::marker::Sized,
I: Stream,
// Force users to deal with `Incomplete` when `StreamIsPartial<true>`
I: StreamIsPartial,
E: ParserError<I>,
<E as ParserError<I>>::Inner: ParserError<I>,
{
debug_assert!(
!I::is_partial_supported(),
"partial streams need to handle `ErrMode::Incomplete`"
);
let start = input.checkpoint();
let (o, _) = (self.by_ref(), crate::combinator::eof)
.parse_next(&mut input)
.map_err(|e| {
let e = e.into_inner().unwrap_or_else(|_err| {
panic!("complete parsers should not report `ErrMode::Incomplete(_)`")
});
ParseError::new(input, start, e)
})?;
Ok(o)
}
/// Take tokens from the [`Stream`], turning it into the output
///
/// This includes advancing the [`Stream`] to the next location.
///
/// On error, `input` will be left pointing at the error location.
fn parse_next(&mut self, input: &mut I) -> Result<O, E>;
/// Take tokens from the [`Stream`], turning it into the output
///
/// This returns a copy of the [`Stream`] advanced to the next location.
///
/// <div class="warning">
///
/// Generally, prefer [`Parser::parse_next`].
/// This is primarily intended for:
/// - Migrating from older versions / `nom`
/// - Testing [`Parser`]s
///
/// For look-ahead parsing, see instead [`peek`][crate::combinator::peek].
///
/// </div>
#[inline(always)]
fn parse_peek(&mut self, mut input: I) -> Result<(I, O), E> {
match self.parse_next(&mut input) {
Ok(o) => Ok((input, o)),
Err(err) => Err(err),
}
}
/// Treat `&mut Self` as a parser
///
/// This helps when needing to move a `Parser` when all you have is a `&mut Parser`.
///
/// # Example
///
/// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f`
/// into [`length_take`][crate::binary::length_take] and `g` into
/// [`Parser::complete_err`]:
/// ```rust,compile_fail
/// # use winnow::prelude::*;
/// # use winnow::Parser;
/// # use winnow::error::ParserError;
/// # use winnow::binary::length_take;
/// pub fn length_value<'i, O, E: ParserError<&'i [u8]>>(
/// mut f: impl Parser<&'i [u8], usize, E>,
/// mut g: impl Parser<&'i [u8], O, E>
/// ) -> impl Parser<&'i [u8], O, E> {
/// move |i: &mut &'i [u8]| {
/// let mut data = length_take(f).parse_next(i)?;
/// let o = g.complete_err().parse_next(&mut data)?;
/// Ok(o)
/// }
/// }
/// ```
///
/// By adding `by_ref`, we can make this work:
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::Parser;
/// # use winnow::error::ParserError;
/// # use winnow::binary::length_take;
/// pub fn length_value<'i, O, E: ParserError<&'i [u8]>>(
/// mut f: impl Parser<&'i [u8], usize, E>,
/// mut g: impl Parser<&'i [u8], O, E>
/// ) -> impl Parser<&'i [u8], O, E> {
/// move |i: &mut &'i [u8]| {
/// let mut data = length_take(f.by_ref()).parse_next(i)?;
/// let o = g.by_ref().complete_err().parse_next(&mut data)?;
/// Ok(o)
/// }
/// }
/// ```
#[inline(always)]
fn by_ref(&mut self) -> impls::ByRef<'_, Self, I, O, E>
where
Self: core::marker::Sized,
{
impls::ByRef {
p: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Produce the provided value
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::alpha1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<i32> {
/// alpha1.value(1234).parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd"), Ok(("", 1234)));
/// assert!(parser.parse_peek("123abcd;").is_err());
/// # }
/// ```
#[doc(alias = "to")]
#[inline(always)]
fn value<O2>(self, val: O2) -> impls::Value<Self, I, O, O2, E>
where
Self: core::marker::Sized,
O2: Clone,
{
impls::Value {
parser: self,
val,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Produce a type's default value
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::alpha1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<u32> {
/// alpha1.default_value().parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd"), Ok(("", 0)));
/// assert!(parser.parse_peek("123abcd;").is_err());
/// # }
/// ```
#[inline(always)]
fn default_value<O2>(self) -> impls::DefaultValue<Self, I, O, O2, E>
where
Self: core::marker::Sized,
O2: core::default::Default,
{
impls::DefaultValue {
parser: self,
o2: Default::default(),
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Discards the output of the `Parser`
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::alpha1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<()> {
/// alpha1.void().parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd"), Ok(("", ())));
/// assert!(parser.parse_peek("123abcd;").is_err());
/// # }
/// ```
#[inline(always)]
fn void(self) -> impls::Void<Self, I, O, E>
where
Self: core::marker::Sized,
{
impls::Void {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Convert the parser's output to another type using [`std::convert::From`]
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::error::ContextError;
/// use winnow::ascii::alpha1;
/// # fn main() {
///
/// fn parser1<'s>(i: &mut &'s str) -> ModalResult<&'s str> {
/// alpha1(i)
/// }
///
/// let mut parser2 = parser1.output_into();
///
/// // the parser converts the &str output of the child parser into a Vec<u8>
/// let bytes: ModalResult<(_, Vec<u8>), _> = parser2.parse_peek("abcd");
/// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
/// # }
/// ```
#[inline(always)]
fn output_into<O2>(self) -> impls::OutputInto<Self, I, O, O2, E>
where
Self: core::marker::Sized,
O: Into<O2>,
{
impls::OutputInto {
parser: self,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Produce the consumed input as produced value.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::{alpha1};
/// use winnow::combinator::separated_pair;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
/// separated_pair(alpha1, ',', alpha1).take().parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd,efgh"), Ok(("", "abcd,efgh")));
/// assert!(parser.parse_peek("abcd;").is_err());
/// # }
/// ```
#[doc(alias = "concat")]
#[doc(alias = "recognize")]
#[inline(always)]
fn take(self) -> impls::Take<Self, I, O, E>
where
Self: core::marker::Sized,
I: Stream,
{
impls::Take {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Produce the consumed input with the output
///
/// Functions similarly to [take][Parser::take] except it
/// returns the parser output as well.
///
/// This can be useful especially in cases where the output is not the same type
/// as the input, or the input is a user defined type.
///
/// Returned tuple is of the format `(produced output, consumed input)`.
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode};
/// use winnow::ascii::{alpha1};
/// use winnow::token::literal;
/// use winnow::combinator::separated_pair;
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<(bool, &'i str)> {
/// separated_pair(alpha1, ',', alpha1).value(true).with_taken().parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd,efgh1"), Ok(("1", (true, "abcd,efgh"))));
/// assert!(parser.parse_peek("abcd;").is_err());
/// ```
#[doc(alias = "consumed")]
#[doc(alias = "with_recognized")]
#[inline(always)]
fn with_taken(self) -> impls::WithTaken<Self, I, O, E>
where
Self: core::marker::Sized,
I: Stream,
{
impls::WithTaken {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Produce the location of the consumed input as produced value.
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, stream::Stream};
/// # use std::ops::Range;
/// use winnow::stream::LocatingSlice;
/// use winnow::ascii::alpha1;
/// use winnow::combinator::separated_pair;
///
/// fn parser<'i>(input: &mut LocatingSlice<&'i str>) -> ModalResult<(Range<usize>, Range<usize>)> {
/// separated_pair(alpha1.span(), ',', alpha1.span()).parse_next(input)
/// }
///
/// assert_eq!(parser.parse(LocatingSlice::new("abcd,efgh")), Ok((0..4, 5..9)));
/// assert!(parser.parse_peek(LocatingSlice::new("abcd;")).is_err());
/// ```
#[inline(always)]
fn span(self) -> impls::Span<Self, I, O, E>
where
Self: core::marker::Sized,
I: Stream + Location,
{
impls::Span {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Produce the location of consumed input with the output
///
/// Functions similarly to [`Parser::span`] except it
/// returns the parser output as well.
///
/// This can be useful especially in cases where the output is not the same type
/// as the input, or the input is a user defined type.
///
/// Returned tuple is of the format `(produced output, consumed input)`.
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, stream::Stream};
/// # use std::ops::Range;
/// use winnow::stream::LocatingSlice;
/// use winnow::ascii::alpha1;
/// use winnow::token::literal;
/// use winnow::combinator::separated_pair;
///
/// fn parser<'i>(input: &mut LocatingSlice<&'i str>) -> ModalResult<((usize, Range<usize>), (usize, Range<usize>))> {
/// separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span()).parse_next(input)
/// }
///
/// assert_eq!(parser.parse(LocatingSlice::new("abcd,efgh")), Ok(((1, 0..4), (2, 5..9))));
/// assert!(parser.parse_peek(LocatingSlice::new("abcd;")).is_err());
/// ```
#[inline(always)]
fn with_span(self) -> impls::WithSpan<Self, I, O, E>
where
Self: core::marker::Sized,
I: Stream + Location,
{
impls::WithSpan {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Maps a function over the output of a parser
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::ascii::digit1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<usize> {
/// digit1.map(|s: &str| s.len()).parse_next(input)
/// }
///
/// // the parser will count how many characters were returned by digit1
/// assert_eq!(parser.parse_peek("123456"), Ok(("", 6)));
///
/// // this will fail if digit1 fails
/// assert!(parser.parse_peek("abc").is_err());
/// # }
/// ```
#[inline(always)]
fn map<G, O2>(self, map: G) -> impls::Map<Self, G, I, O, O2, E>
where
G: FnMut(O) -> O2,
Self: core::marker::Sized,
{
impls::Map {
parser: self,
map,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Applies a function returning a `Result` over the output of a parser.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::digit1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<u8> {
/// digit1.try_map(|s: &str| s.parse::<u8>()).parse_next(input)
/// }
///
/// // the parser will convert the result of digit1 to a number
/// assert_eq!(parser.parse_peek("123"), Ok(("", 123)));
///
/// // this will fail if digit1 fails
/// assert!(parser.parse_peek("abc").is_err());
///
/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
/// assert!(parser.parse_peek("123456").is_err());
/// # }
/// ```
#[inline(always)]
fn try_map<G, O2, E2>(self, map: G) -> impls::TryMap<Self, G, I, O, O2, E, E2>
where
Self: core::marker::Sized,
G: FnMut(O) -> Result<O2, E2>,
I: Stream,
E: FromExternalError<I, E2>,
E: ParserError<I>,
{
impls::TryMap {
parser: self,
map,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
e2: Default::default(),
}
}
/// Apply both [`Parser::verify`] and [`Parser::map`].
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::digit1;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<u8> {
/// digit1.verify_map(|s: &str| s.parse::<u8>().ok()).parse_next(input)
/// }
///
/// // the parser will convert the result of digit1 to a number
/// assert_eq!(parser.parse_peek("123"), Ok(("", 123)));
///
/// // this will fail if digit1 fails
/// assert!(parser.parse_peek("abc").is_err());
///
/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
/// assert!(parser.parse_peek("123456").is_err());
/// # }
/// ```
#[doc(alias = "satisfy_map")]
#[doc(alias = "filter_map")]
#[doc(alias = "map_opt")]
#[inline(always)]
fn verify_map<G, O2>(self, map: G) -> impls::VerifyMap<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
G: FnMut(O) -> Option<O2>,
I: Stream,
E: ParserError<I>,
{
impls::VerifyMap {
parser: self,
map,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Creates a parser from the output of this one
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, ModalResult, Parser};
/// use winnow::token::take;
/// use winnow::binary::u8;
///
/// fn length_take<'s>(input: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// u8.flat_map(take).parse_next(input)
/// }
///
/// assert_eq!(length_take.parse_peek(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
/// assert!(length_take.parse_peek(&[4, 0, 1, 2][..]).is_err());
/// ```
///
/// which is the same as
/// ```rust
/// # use winnow::{error::ErrMode, ModalResult, Parser};
/// use winnow::token::take;
/// use winnow::binary::u8;
///
/// fn length_take<'s>(input: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// let length = u8.parse_next(input)?;
/// let data = take(length).parse_next(input)?;
/// Ok(data)
/// }
///
/// assert_eq!(length_take.parse_peek(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
/// assert!(length_take.parse_peek(&[4, 0, 1, 2][..]).is_err());
/// ```
#[inline(always)]
fn flat_map<G, H, O2>(self, map: G) -> impls::FlatMap<Self, G, H, I, O, O2, E>
where
Self: core::marker::Sized,
G: FnMut(O) -> H,
H: Parser<I, O2, E>,
{
impls::FlatMap {
f: self,
g: map,
h: Default::default(),
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Applies a second parser over the output of the first one
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::prelude::*;
/// use winnow::ascii::digit1;
/// use winnow::token::take;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
/// take(5u8).and_then(digit1).parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("12345"), Ok(("", "12345")));
/// assert_eq!(parser.parse_peek("123ab"), Ok(("", "123")));
/// assert!(parser.parse_peek("123").is_err());
/// # }
/// ```
#[inline(always)]
fn and_then<G, O2>(self, inner: G) -> impls::AndThen<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
G: Parser<O, O2, E>,
O: StreamIsPartial,
I: Stream,
{
impls::AndThen {
outer: self,
inner,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Apply [`std::str::FromStr`] to the output of the parser
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// use winnow::{error::ErrMode, Parser};
/// use winnow::ascii::digit1;
///
/// fn parser<'s>(input: &mut &'s str) -> ModalResult<u64> {
/// digit1.parse_to().parse_next(input)
/// }
///
/// // the parser will count how many characters were returned by digit1
/// assert_eq!(parser.parse_peek("123456"), Ok(("", 123456)));
///
/// // this will fail if digit1 fails
/// assert!(parser.parse_peek("abc").is_err());
/// ```
#[doc(alias = "from_str")]
#[inline(always)]
fn parse_to<O2>(self) -> impls::ParseTo<Self, I, O, O2, E>
where
Self: core::marker::Sized,
I: Stream,
O: ParseSlice<O2>,
E: ParserError<I>,
{
impls::ParseTo {
p: self,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// Returns the output of the child parser if it satisfies a verification function.
///
/// The verification function takes as argument a reference to the output of the
/// parser.
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::ascii::alpha1;
/// # use winnow::prelude::*;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
/// alpha1.verify(|s: &str| s.len() == 4).parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("abcd"), Ok(("", "abcd")));
/// assert!(parser.parse_peek("abcde").is_err());
/// assert!(parser.parse_peek("123abcd;").is_err());
/// # }
/// ```
#[doc(alias = "satisfy")]
#[doc(alias = "filter")]
#[inline(always)]
fn verify<G, O2>(self, filter: G) -> impls::Verify<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
G: FnMut(&O2) -> bool,
I: Stream,
O: crate::lib::std::borrow::Borrow<O2>,
O2: ?Sized,
E: ParserError<I>,
{
impls::Verify {
parser: self,
filter,
i: Default::default(),
o: Default::default(),
o2: Default::default(),
e: Default::default(),
}
}
/// If parsing fails, add context to the error
///
/// This is used mainly to add user friendly information
/// to errors when backtracking through a parse tree.
///
/// See also [tutorial][crate::_tutorial::chapter_7].
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::ascii::digit1;
/// # use winnow::error::StrContext;
/// # use winnow::error::StrContextValue;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
/// digit1
/// .context(StrContext::Expected(StrContextValue::Description("digit")))
/// .parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
/// assert!(parser.parse_peek("abc").is_err());
/// # }
/// ```
#[doc(alias = "labelled")]
#[inline(always)]
fn context<C>(self, context: C) -> impls::Context<Self, I, O, E, C>
where
Self: core::marker::Sized,
I: Stream,
E: AddContext<I, C>,
E: ParserError<I>,
C: Clone + crate::lib::std::fmt::Debug,
{
impls::Context {
parser: self,
context,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// If parsing fails, dynamically add context to the error
///
/// This is used mainly to add user friendly information
/// to errors when backtracking through a parse tree.
///
/// See also [tutorial][crate::_tutorial::chapter_7].
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, Parser};
/// # use winnow::ascii::digit1;
/// # use winnow::error::StrContext;
/// # use winnow::error::StrContextValue;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> ModalResult<&'i str> {
/// digit1
/// .context_with(|| {
/// "0123456789".chars().map(|c| StrContext::Expected(c.into()))
/// })
/// .parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
/// assert!(parser.parse_peek("abc").is_err());
/// # }
/// ```
#[doc(alias = "labelled")]
#[inline(always)]
fn context_with<F, C, FI>(self, context: F) -> impls::ContextWith<Self, I, O, E, F, C, FI>
where
Self: core::marker::Sized,
I: Stream,
E: AddContext<I, C>,
E: ParserError<I>,
F: Fn() -> FI + Clone,
C: crate::lib::std::fmt::Debug,
FI: Iterator<Item = C>,
{
impls::ContextWith {
parser: self,
context,
i: Default::default(),
o: Default::default(),
e: Default::default(),
c: Default::default(),
fi: Default::default(),
}
}
/// Maps a function over the error of a parser
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::Parser;
/// # use winnow::Result;
/// # use winnow::ascii::digit1;
/// # use winnow::error::StrContext;
/// # use winnow::error::AddContext;
/// # use winnow::error::ContextError;
/// # fn main() {
///
/// fn parser<'i>(input: &mut &'i str) -> Result<&'i str> {
/// digit1.map_err(|mut e: ContextError| {
/// e.extend("0123456789".chars().map(|c| StrContext::Expected(c.into())));
/// e
/// }).parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek("123456"), Ok(("", "123456")));
/// assert!(parser.parse_peek("abc").is_err());
/// # }
/// ```
#[inline(always)]
fn map_err<G, E2>(self, map: G) -> impls::MapErr<Self, G, I, O, E, E2>
where
G: FnMut(E) -> E2,
Self: core::marker::Sized,
{
impls::MapErr {
parser: self,
map,
i: Default::default(),
o: Default::default(),
e: Default::default(),
e2: Default::default(),
}
}
/// Transforms [`Incomplete`][crate::error::ErrMode::Incomplete] into [`Backtrack`][crate::error::ErrMode::Backtrack]
///
/// # Example
///
/// ```rust
/// # use winnow::{error::ErrMode, error::InputError, stream::Partial, Parser};
/// # use winnow::token::take;
/// # use winnow::prelude::*;
/// # fn main() {
///
/// fn parser<'i>(input: &mut Partial<&'i str>) -> ModalResult<&'i str, InputError<Partial<&'i str>>> {
/// take(5u8).complete_err().parse_next(input)
/// }
///
/// assert_eq!(parser.parse_peek(Partial::new("abcdefg")), Ok((Partial::new("fg"), "abcde")));
/// assert_eq!(parser.parse_peek(Partial::new("abcd")), Err(ErrMode::Backtrack(InputError::at(Partial::new("abcd")))));
/// # }
/// ```
#[inline(always)]
fn complete_err(self) -> impls::CompleteErr<Self, I, O, E>
where
Self: core::marker::Sized,
{
impls::CompleteErr {
p: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Convert the parser's error to another type using [`std::convert::From`]
#[inline(always)]
fn err_into<E2>(self) -> impls::ErrInto<Self, I, O, E, E2>
where
Self: core::marker::Sized,
E: Into<E2>,
{
impls::ErrInto {
parser: self,
i: Default::default(),
o: Default::default(),
e: Default::default(),
e2: Default::default(),
}
}
/// Recover from an error by skipping everything `recover` consumes and trying again
///
/// If `recover` consumes nothing, the error is returned, allowing an alternative recovery
/// method.
///
/// This commits the parse result, preventing alternative branch paths like with
/// [`winnow::combinator::alt`][crate::combinator::alt].
#[inline(always)]
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
fn retry_after<R>(self, recover: R) -> impls::RetryAfter<Self, R, I, O, E>
where
Self: core::marker::Sized,
R: Parser<I, (), E>,
I: Stream,
I: Recover<E>,
E: ParserError<I> + FromRecoverableError<I, E>,
{
impls::RetryAfter {
parser: self,
recover,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
/// Recover from an error by skipping this parse and everything `recover` consumes
///
/// This commits the parse result, preventing alternative branch paths like with
/// [`winnow::combinator::alt`][crate::combinator::alt].
#[inline(always)]
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
fn resume_after<R>(self, recover: R) -> impls::ResumeAfter<Self, R, I, O, E>
where
Self: core::marker::Sized,
R: Parser<I, (), E>,
I: Stream,
I: Recover<E>,
E: ParserError<I> + FromRecoverableError<I, E>,
{
impls::ResumeAfter {
parser: self,
recover,
i: Default::default(),
o: Default::default(),
e: Default::default(),
}
}
}
impl<I, O, E, F> Parser<I, O, E> for F
where
F: FnMut(&mut I) -> Result<O, E>,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<O, E> {
self(i)
}
}
/// This is a shortcut for [`one_of`][crate::token::one_of].
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError};
/// fn parser<'s>(i: &mut &'s [u8]) -> ModalResult<u8> {
/// b'a'.parse_next(i)
/// }
/// assert_eq!(parser.parse_peek(&b"abc"[..]), Ok((&b"bc"[..], b'a')));
/// assert!(parser.parse_peek(&b" abc"[..]).is_err());
/// assert!(parser.parse_peek(&b"bc"[..]).is_err());
/// assert!(parser.parse_peek(&b""[..]).is_err());
/// ```
impl<I, E> Parser<I, u8, E> for u8
where
I: StreamIsPartial,
I: Stream,
I: Compare<u8>,
E: ParserError<I>,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<u8, E> {
crate::token::literal(*self).value(*self).parse_next(i)
}
}
/// This is a shortcut for [`one_of`][crate::token::one_of].
///
/// # Example
///
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError};
/// fn parser<'s>(i: &mut &'s str) -> ModalResult<char> {
/// 'a'.parse_next(i)
/// }
/// assert_eq!(parser.parse_peek("abc"), Ok(("bc", 'a')));
/// assert!(parser.parse_peek(" abc").is_err());
/// assert!(parser.parse_peek("bc").is_err());
/// assert!(parser.parse_peek("").is_err());
/// ```
impl<I, E> Parser<I, char, E> for char
where
I: StreamIsPartial,
I: Stream,
I: Compare<char>,
E: ParserError<I>,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<char, E> {
crate::token::literal(*self).value(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
///
/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// alt((&"Hello"[..], take(5usize))).parse_next(s)
/// }
///
/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
/// assert!(parser.parse_peek(&b""[..]).is_err());
/// ```
impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s [u8]
where
I: Compare<&'s [u8]> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
/// use winnow::ascii::Caseless;
///
/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// alt((Caseless(&"hello"[..]), take(5usize))).parse_next(s)
/// }
///
/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
/// assert_eq!(parser.parse_peek(&b"hello, World!"[..]), Ok((&b", World!"[..], &b"hello"[..])));
/// assert_eq!(parser.parse_peek(&b"HeLlo, World!"[..]), Ok((&b", World!"[..], &b"HeLlo"[..])));
/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
/// assert!(parser.parse_peek(&b""[..]).is_err());
/// ```
impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for AsciiCaseless<&'s [u8]>
where
I: Compare<AsciiCaseless<&'s [u8]>> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
///
/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// alt((b"Hello", take(5usize))).parse_next(s)
/// }
///
/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
/// assert!(parser.parse_peek(&b""[..]).is_err());
/// ```
impl<'s, I, E: ParserError<I>, const N: usize> Parser<I, <I as Stream>::Slice, E> for &'s [u8; N]
where
I: Compare<&'s [u8; N]> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError, error::Needed};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
/// use winnow::ascii::Caseless;
///
/// fn parser<'s>(s: &mut &'s [u8]) -> ModalResult<&'s [u8]> {
/// alt((Caseless(b"hello"), take(5usize))).parse_next(s)
/// }
///
/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
/// assert_eq!(parser.parse_peek(&b"hello, World!"[..]), Ok((&b", World!"[..], &b"hello"[..])));
/// assert_eq!(parser.parse_peek(&b"HeLlo, World!"[..]), Ok((&b", World!"[..], &b"HeLlo"[..])));
/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
/// assert!(parser.parse_peek(&b"Some"[..]).is_err());
/// assert!(parser.parse_peek(&b""[..]).is_err());
/// ```
impl<'s, I, E: ParserError<I>, const N: usize> Parser<I, <I as Stream>::Slice, E>
for AsciiCaseless<&'s [u8; N]>
where
I: Compare<AsciiCaseless<&'s [u8; N]>> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
///
/// fn parser<'s>(s: &mut &'s str) -> ModalResult<&'s str> {
/// alt(("Hello", take(5usize))).parse_next(s)
/// }
///
/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
/// assert_eq!(parser.parse_peek("Something"), Ok(("hing", "Somet")));
/// assert!(parser.parse_peek("Some").is_err());
/// assert!(parser.parse_peek("").is_err());
/// ```
impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for &'s str
where
I: Compare<&'s str> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
/// This is a shortcut for [`literal`][crate::token::literal].
///
/// # Example
/// ```rust
/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::ContextError};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
/// # use winnow::ascii::Caseless;
///
/// fn parser<'s>(s: &mut &'s str) -> ModalResult<&'s str> {
/// alt((Caseless("hello"), take(5usize))).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_eq!(parser.parse_peek("Something"), Ok(("hing", "Somet")));
/// assert!(parser.parse_peek("Some").is_err());
/// assert!(parser.parse_peek("").is_err());
/// ```
impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for AsciiCaseless<&'s str>
where
I: Compare<AsciiCaseless<&'s str>> + StreamIsPartial,
I: Stream,
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<<I as Stream>::Slice, E> {
crate::token::literal(*self).parse_next(i)
}
}
impl<I: Stream, E: ParserError<I>> Parser<I, (), E> for () {
#[inline(always)]
fn parse_next(&mut self, _i: &mut I) -> Result<(), E> {
Ok(())
}
}
macro_rules! impl_parser_for_tuple {
($($index:tt $parser:ident $output:ident),+) => (
#[allow(non_snake_case)]
impl<I: Stream, $($output),+, E: ParserError<I>, $($parser),+> Parser<I, ($($output),+,), E> for ($($parser),+,)
where
$($parser: Parser<I, $output, E>),+
{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<($($output),+,), E> {
$(let $output = self.$index.parse_next(i)?;)+
Ok(($($output),+,))
}
}
)
}
macro_rules! impl_parser_for_tuples {
($index1:tt $parser1:ident $output1:ident, $($index:tt $parser:ident $output:ident),+) => {
impl_parser_for_tuples!(__impl $index1 $parser1 $output1; $($index $parser $output),+);
};
(__impl $($index:tt $parser:ident $output:ident),+; $index1:tt $parser1:ident $output1:ident $(,$index2:tt $parser2:ident $output2:ident)*) => {
impl_parser_for_tuple!($($index $parser $output),+);
impl_parser_for_tuples!(__impl $($index $parser $output),+, $index1 $parser1 $output1; $($index2 $parser2 $output2),*);
};
(__impl $($index:tt $parser:ident $output:ident),+;) => {
impl_parser_for_tuple!($($index $parser $output),+);
}
}
impl_parser_for_tuples!(
0 P0 O0,
1 P1 O1,
2 P2 O2,
3 P3 O3,
4 P4 O4,
5 P5 O5,
6 P6 O6,
7 P7 O7,
8 P8 O8,
9 P9 O9,
10 P10 O10,
11 P11 O11,
12 P12 O12,
13 P13 O13,
14 P14 O14,
15 P15 O15,
16 P16 O16,
17 P17 O17,
18 P18 O18,
19 P19 O19,
20 P20 O20,
21 P21 O21
);
#[cfg(feature = "alloc")]
use crate::lib::std::boxed::Box;
#[cfg(feature = "alloc")]
impl<I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + '_> {
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> Result<O, E> {
(**self).parse_next(i)
}
}
/// Trait alias for [`Parser`] to be used with [`ModalResult`][crate::error::ModalResult]
pub trait ModalParser<I, O, E>: Parser<I, O, crate::error::ErrMode<E>> {}
impl<I, O, E, P> ModalParser<I, O, E> for P where P: Parser<I, O, crate::error::ErrMode<E>> {}
/// Collect all errors when parsing the input
///
/// [`Parser`]s will need to use [`Recoverable<I, _>`] for their input.
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
pub trait RecoverableParser<I, O, R, E> {
/// Collect all errors when parsing the input
///
/// If `self` fails, this acts like [`Parser::resume_after`] and returns `Ok(None)`.
/// Generally, this should be avoided by using
/// [`Parser::retry_after`] and [`Parser::resume_after`] throughout your parser.
///
/// The empty `input` is returned to allow turning the errors into [`ParserError`]s.
fn recoverable_parse(&mut self, input: I) -> (I, Option<O>, Vec<R>);
}
#[cfg(feature = "unstable-recover")]
#[cfg(feature = "std")]
impl<P, I, O, R, E> RecoverableParser<I, O, R, E> for P
where
P: Parser<Recoverable<I, R>, O, E>,
I: Stream,
I: StreamIsPartial,
R: FromRecoverableError<Recoverable<I, R>, E>,
R: crate::lib::std::fmt::Debug,
E: FromRecoverableError<Recoverable<I, R>, E>,
E: ParserError<Recoverable<I, R>>,
E: crate::lib::std::fmt::Debug,
{
fn recoverable_parse(&mut self, input: I) -> (I, Option<O>, Vec<R>) {
debug_assert!(
!I::is_partial_supported(),
"partial streams need to handle `ErrMode::Incomplete`"
);
let start = input.checkpoint();
let mut input = Recoverable::new(input);
let start_token = input.checkpoint();
let result = (
self.by_ref(),
crate::combinator::eof.resume_after(crate::token::rest.void()),
)
.parse_next(&mut input);
let (o, err) = match result {
Ok((o, _)) => (Some(o), None),
Err(err) => {
let err_start = input.checkpoint();
let err = R::from_recoverable_error(&start_token, &err_start, &input, err);
(None, Some(err))
}
};
let (mut input, mut errs) = input.into_parts();
input.reset(&start);
if let Some(err) = err {
errs.push(err);
}
(input, o, errs)
}
}
#[cfg(test)]
mod tests {
use super::*;
use snapbox::prelude::*;
use snapbox::str;
use crate::binary::be_u16;
use crate::error::ErrMode;
use crate::error::Needed;
use crate::error::TestResult;
use crate::token::take;
use crate::Partial;
#[doc(hidden)]
#[macro_export]
macro_rules! assert_size (
($t:ty, $sz:expr) => (
assert!($crate::lib::std::mem::size_of::<$t>() <= $sz, "{} <= {} failed", $crate::lib::std::mem::size_of::<$t>(), $sz);
);
);
#[test]
#[cfg(target_pointer_width = "64")]
fn size_test() {
assert_size!(Result<&[u8], (&[u8], u32)>, 40);
assert_size!(Result<&str, u32>, 40);
assert_size!(Needed, 8);
assert_size!(ErrMode<u32>, 16);
}
#[test]
fn err_map_test() {
let e = ErrMode::Backtrack(1);
assert_eq!(e.map(|v| v + 1), ErrMode::Backtrack(2));
}
#[test]
fn single_element_tuples() {
use crate::ascii::alpha1;
let mut parser = (alpha1,);
assert_parse!(
parser.parse_peek("abc123def"),
str![[r#"
Ok(
(
"123def",
(
"abc",
),
),
)
"#]]
.raw()
);
assert_parse!(
parser.parse_peek("123def"),
str![[r#"
Err(
Backtrack(
InputError {
input: "123def",
},
),
)
"#]]
.raw()
);
}
#[test]
fn tuple_test() {
#[allow(clippy::type_complexity)]
fn tuple_3<'i>(
i: &mut Partial<&'i [u8]>,
) -> TestResult<Partial<&'i [u8]>, (u16, &'i [u8], &'i [u8])> {
(be_u16, take(3u8), "fg").parse_next(i)
}
assert_parse!(
tuple_3.parse_peek(Partial::new(&b"abcdefgh"[..])),
str![[r#"
Ok(
(
Partial {
input: [
104,
],
partial: true,
},
(
24930,
[
99,
100,
101,
],
[
102,
103,
],
),
),
)
"#]]
.raw()
);
assert_parse!(
tuple_3.parse_peek(Partial::new(&b"abcd"[..])),
str![[r#"
Err(
Incomplete(
Size(
1,
),
),
)
"#]]
.raw()
);
assert_parse!(
tuple_3.parse_peek(Partial::new(&b"abcde"[..])),
str![[r#"
Err(
Incomplete(
Unknown,
),
)
"#]]
.raw()
);
assert_parse!(
tuple_3.parse_peek(Partial::new(&b"abcdejk"[..])),
str![[r#"
Err(
Backtrack(
InputError {
input: Partial {
input: [
106,
107,
],
partial: true,
},
},
),
)
"#]]
.raw()
);
}
#[test]
fn unit_type() {
fn parser<'i>(i: &mut &'i str) -> TestResult<&'i str, ()> {
().parse_next(i)
}
assert_parse!(
parser.parse_peek("abxsbsh"),
str![[r#"
Ok(
(
"abxsbsh",
(),
),
)
"#]]
.raw()
);
assert_parse!(
parser.parse_peek("sdfjakdsas"),
str![[r#"
Ok(
(
"sdfjakdsas",
(),
),
)
"#]]
.raw()
);
assert_parse!(
parser.parse_peek(""),
str![[r#"
Ok(
(
"",
(),
),
)
"#]]
.raw()
);
}
}