somen/parser/wrapper/
satisfy.rs

1use core::pin::Pin;
2use core::task::Context;
3
4use crate::error::{Error, Expects, PolledResult, Status};
5use crate::parser::Parser;
6use crate::stream::Positioned;
7
8/// A parser for method [`satisfy`].
9///
10/// [`satisfy`]: crate::parser::ParserExt::satisfy
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct Satisfy<P, F> {
13    inner: P,
14    f: F,
15}
16
17impl<P, F> Satisfy<P, F> {
18    /// Creates a new instance.
19    #[inline]
20    pub fn new(inner: P, f: F) -> Self {
21        Self { inner, f }
22    }
23
24    /// Extracts the inner parser.
25    #[inline]
26    pub fn into_inner(self) -> P {
27        self.inner
28    }
29}
30
31crate::parser_state! {
32    pub struct SatisfyState<I, P: Parser> {
33        inner: P::State,
34        #[opt(set = set_start)]
35        start: I::Locator,
36    }
37}
38
39impl<P, F, I> Parser<I> for Satisfy<P, F>
40where
41    P: Parser<I>,
42    F: FnMut(&P::Output) -> bool,
43    I: Positioned + ?Sized,
44{
45    type Output = P::Output;
46    type State = SatisfyState<I, P>;
47
48    fn poll_parse(
49        &mut self,
50        mut input: Pin<&mut I>,
51        cx: &mut Context<'_>,
52        state: &mut Self::State,
53    ) -> PolledResult<Self::Output, I> {
54        state.set_start(|| input.position());
55        self.inner
56            .poll_parse(input.as_mut(), cx, &mut state.inner)
57            .map_ok(|status| match status {
58                Status::Success(val, err) if (self.f)(&val) => Status::Success(val, err),
59                Status::Success(_, _) => Status::Failure(
60                    Error {
61                        expects: Expects::from("<condition>"),
62                        position: state.start()..input.position(),
63                    },
64                    true,
65                ),
66                Status::Failure(err, exclusive) => Status::Failure(err, exclusive),
67            })
68    }
69}