use crate::combinator::*;
use crate::error::{ContextError, IResult, ParseError};
use crate::stream::{AsChar, Compare, Location, Stream, StreamIsPartial};
pub trait Parser<I, O, E> {
#[deprecated(since = "0.3.0", note = "Replaced with `Parser::parse_next`")]
#[cfg_attr(feature = "unstable-doc", doc(hidden))]
#[inline(always)]
fn parse(&mut self, input: I) -> IResult<I, O, E> {
self.parse_next(input)
}
fn parse_next(&mut self, input: I) -> IResult<I, O, E>;
#[inline(always)]
fn by_ref(&mut self) -> ByRef<'_, Self>
where
Self: core::marker::Sized,
{
ByRef::new(self)
}
#[doc(alias = "to")]
#[inline(always)]
fn value<O2>(self, val: O2) -> Value<Self, O, O2>
where
Self: core::marker::Sized,
O2: Clone,
{
Value::new(self, val)
}
#[inline(always)]
fn void(self) -> Void<Self, O>
where
Self: core::marker::Sized,
{
Void::new(self)
}
#[inline(always)]
fn output_into<O2>(self) -> OutputInto<Self, O, O2>
where
Self: core::marker::Sized,
O: Into<O2>,
{
OutputInto::new(self)
}
#[doc(alias = "concat")]
#[inline(always)]
fn recognize(self) -> Recognize<Self, O>
where
Self: core::marker::Sized,
{
Recognize::new(self)
}
#[doc(alias = "consumed")]
#[inline(always)]
fn with_recognized(self) -> WithRecognized<Self, O>
where
Self: core::marker::Sized,
{
WithRecognized::new(self)
}
#[inline(always)]
fn span(self) -> Span<Self, O>
where
Self: core::marker::Sized,
I: Location + Clone,
{
Span::new(self)
}
#[inline(always)]
fn with_span(self) -> WithSpan<Self, O>
where
Self: core::marker::Sized,
I: Location + Clone,
{
WithSpan::new(self)
}
#[inline(always)]
fn map<G, O2>(self, g: G) -> Map<Self, G, O>
where
G: Fn(O) -> O2,
Self: core::marker::Sized,
{
Map::new(self, g)
}
#[inline(always)]
fn map_res<G, O2, E2>(self, g: G) -> MapRes<Self, G, O>
where
Self: core::marker::Sized,
G: FnMut(O) -> Result<O2, E2>,
{
MapRes::new(self, g)
}
#[doc(alias = "satisfy_map")]
#[doc(alias = "filter_map")]
#[doc(alias = "map_opt")]
#[inline(always)]
fn verify_map<G, O2>(self, g: G) -> VerifyMap<Self, G, O>
where
Self: core::marker::Sized,
G: FnMut(O) -> Option<O2>,
{
VerifyMap::new(self, g)
}
#[inline(always)]
fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
where
G: FnMut(O) -> H,
H: Parser<I, O2, E>,
Self: core::marker::Sized,
{
FlatMap::new(self, g)
}
#[inline(always)]
fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
where
O: StreamIsPartial,
G: Parser<O, O2, E>,
Self: core::marker::Sized,
{
AndThen::new(self, g)
}
#[doc(alias = "from_str")]
#[inline(always)]
fn parse_to<O2>(self) -> ParseTo<Self, O, O2>
where
Self: core::marker::Sized,
O: crate::stream::ParseSlice<O2>,
{
ParseTo::new(self)
}
#[doc(alias = "satisfy")]
#[doc(alias = "filter")]
#[inline(always)]
fn verify<G, O2: ?Sized>(self, second: G) -> Verify<Self, G, O2>
where
Self: core::marker::Sized,
G: Fn(&O2) -> bool,
{
Verify::new(self, second)
}
#[doc(alias = "labelled")]
#[inline(always)]
fn context<C>(self, context: C) -> Context<Self, O, C>
where
Self: core::marker::Sized,
C: Clone + crate::lib::std::fmt::Debug,
E: ContextError<I, C>,
{
Context::new(self, context)
}
#[inline(always)]
fn complete_err(self) -> CompleteErr<Self>
where
Self: core::marker::Sized,
{
CompleteErr::new(self)
}
#[inline(always)]
fn err_into<E2>(self) -> ErrInto<Self, E, E2>
where
Self: core::marker::Sized,
E: Into<E2>,
{
ErrInto::new(self)
}
#[deprecated(since = "0.1.0", note = "Replaced with `winnow::sequence::tuple")]
#[cfg_attr(feature = "unstable-doc", doc(hidden))]
#[inline(always)]
fn and<G, O2>(self, g: G) -> And<Self, G>
where
G: Parser<I, O2, E>,
Self: core::marker::Sized,
{
And::new(self, g)
}
#[deprecated(since = "0.1.0", note = "Replaced with `winnow::branch::alt")]
#[cfg_attr(feature = "unstable-doc", doc(hidden))]
#[inline(always)]
fn or<G>(self, g: G) -> Or<Self, G>
where
G: Parser<I, O, E>,
Self: core::marker::Sized,
{
Or::new(self, g)
}
}
impl<'a, I, O, E, F> Parser<I, O, E> for F
where
F: FnMut(I) -> IResult<I, O, E> + 'a,
{
#[inline(always)]
fn parse_next(&mut self, i: I) -> IResult<I, O, E> {
self(i)
}
}
impl<I, E> Parser<I, u8, E> for u8
where
I: StreamIsPartial,
I: Stream<Token = u8>,
E: ParseError<I>,
{
#[inline(always)]
fn parse_next(&mut self, i: I) -> IResult<I, u8, E> {
crate::bytes::one_of(*self).parse_next(i)
}
}
impl<I, E> Parser<I, <I as Stream>::Token, E> for char
where
I: StreamIsPartial,
I: Stream,
<I as Stream>::Token: AsChar + Copy,
E: ParseError<I>,
{
#[inline(always)]
fn parse_next(&mut self, i: I) -> IResult<I, <I as Stream>::Token, E> {
crate::bytes::one_of(*self).parse_next(i)
}
}
impl<'s, I, E: ParseError<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: I) -> IResult<I, <I as Stream>::Slice, E> {
crate::bytes::tag(*self).parse_next(i)
}
}
impl<'s, I, E: ParseError<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: I) -> IResult<I, <I as Stream>::Slice, E> {
crate::bytes::tag(*self).parse_next(i)
}
}
impl<'s, I, E: ParseError<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: I) -> IResult<I, <I as Stream>::Slice, E> {
crate::bytes::tag(*self).parse_next(i)
}
}
impl<I, E: ParseError<I>> Parser<I, (), E> for () {
#[inline(always)]
fn parse_next(&mut self, i: I) -> IResult<I, (), E> {
Ok((i, ()))
}
}
macro_rules! impl_parser_for_tuple {
($($parser:ident $output:ident),+) => (
#[allow(non_snake_case)]
impl<I, $($output),+, E: ParseError<I>, $($parser),+> Parser<I, ($($output),+,), E> for ($($parser),+,)
where
$($parser: Parser<I, $output, E>),+
{
#[inline(always)]
fn parse_next(&mut self, i: I) -> IResult<I, ($($output),+,), E> {
let ($(ref mut $parser),+,) = *self;
$(let(i, $output) = $parser.parse_next(i)?;)+
Ok((i, ($($output),+,)))
}
}
)
}
macro_rules! impl_parser_for_tuples {
($parser1:ident $output1:ident, $($parser:ident $output:ident),+) => {
impl_parser_for_tuples!(__impl $parser1 $output1; $($parser $output),+);
};
(__impl $($parser:ident $output:ident),+; $parser1:ident $output1:ident $(,$parser2:ident $output2:ident)*) => {
impl_parser_for_tuple!($($parser $output),+);
impl_parser_for_tuples!(__impl $($parser $output),+, $parser1 $output1; $($parser2 $output2),*);
};
(__impl $($parser:ident $output:ident),+;) => {
impl_parser_for_tuple!($($parser $output),+);
}
}
impl_parser_for_tuples!(
P1 O1,
P2 O2,
P3 O3,
P4 O4,
P5 O5,
P6 O6,
P7 O7,
P8 O8,
P9 O9,
P10 O10,
P11 O11,
P12 O12,
P13 O13,
P14 O14,
P15 O15,
P16 O16,
P17 O17,
P18 O18,
P19 O19,
P20 O20,
P21 O21
);
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
impl<'a, I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + 'a> {
#[inline(always)]
fn parse_next(&mut self, input: I) -> IResult<I, O, E> {
(**self).parse_next(input)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::bytes::{tag, take};
use crate::error::ErrMode;
use crate::error::Error;
use crate::error::ErrorKind;
use crate::error::Needed;
use crate::number::be_u16;
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!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
assert_size!(IResult<&str, &str, u32>, 40);
assert_size!(Needed, 8);
assert_size!(ErrMode<u32>, 16);
assert_size!(ErrorKind, 1);
}
#[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::character::alpha1;
use crate::error::ErrorKind;
let mut parser = (alpha1,);
assert_eq!(parser.parse_next("abc123def"), Ok(("123def", ("abc",))));
assert_eq!(
parser.parse_next("123def"),
Err(ErrMode::Backtrack(Error {
input: "123def",
kind: ErrorKind::Alpha
}))
);
}
#[test]
fn tuple_test() {
#[allow(clippy::type_complexity)]
fn tuple_3(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (u16, &[u8], &[u8])> {
(be_u16, take(3u8), tag("fg")).parse_next(i)
}
assert_eq!(
tuple_3(Partial::new(&b"abcdefgh"[..])),
Ok((
Partial::new(&b"h"[..]),
(0x6162u16, &b"cde"[..], &b"fg"[..])
))
);
assert_eq!(
tuple_3(Partial::new(&b"abcd"[..])),
Err(ErrMode::Incomplete(Needed::new(1)))
);
assert_eq!(
tuple_3(Partial::new(&b"abcde"[..])),
Err(ErrMode::Incomplete(Needed::new(2)))
);
assert_eq!(
tuple_3(Partial::new(&b"abcdejk"[..])),
Err(ErrMode::Backtrack(error_position!(
Partial::new(&b"jk"[..]),
ErrorKind::Tag
)))
);
}
#[test]
fn unit_type() {
fn parser(i: &str) -> IResult<&str, ()> {
().parse_next(i)
}
assert_eq!(parser.parse_next("abxsbsh"), Ok(("abxsbsh", ())));
assert_eq!(parser.parse_next("sdfjakdsas"), Ok(("sdfjakdsas", ())));
assert_eq!(parser.parse_next(""), Ok(("", ())));
}
}