somen/parser/iterable/combinator/
last.rs

1use core::pin::Pin;
2use core::task::{Context, Poll};
3use futures_core::ready;
4
5use crate::error::{Error, PolledResult, Status};
6use crate::parser::iterable::IterableParser;
7use crate::parser::utils::merge_errors;
8use crate::parser::Parser;
9use crate::stream::Positioned;
10
11/// A parser for method [`last`].
12///
13/// [`last`]: crate::parser::iterable::IterableParserExt::last
14#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct Last<P> {
16    inner: P,
17}
18
19impl<P> Last<P> {
20    /// Creates a new instance.
21    #[inline]
22    pub fn new(inner: P) -> Self {
23        Self { inner }
24    }
25
26    /// Extracts the inner parser.
27    #[inline]
28    pub fn into_inner(self) -> P {
29        self.inner
30    }
31}
32
33crate::parser_state! {
34    pub struct LastState<I, P: IterableParser> {
35        inner: P::State,
36        output: Option<P::Item>,
37        error: Option<Error<I::Locator>>,
38    }
39}
40
41impl<P, I> Parser<I> for Last<P>
42where
43    P: IterableParser<I>,
44    I: Positioned + ?Sized,
45{
46    type Output = Option<P::Item>;
47    type State = LastState<I, P>;
48
49    fn poll_parse(
50        &mut self,
51        mut input: Pin<&mut I>,
52        cx: &mut Context<'_>,
53        state: &mut Self::State,
54    ) -> PolledResult<Self::Output, I> {
55        Poll::Ready(Ok(loop {
56            match ready!(self
57                .inner
58                .poll_parse_next(input.as_mut(), cx, &mut state.inner)?)
59            {
60                Status::Success(Some(val), err) => {
61                    state.output = Some(val);
62                    merge_errors(&mut state.error, err);
63                }
64                Status::Success(None, err) => {
65                    merge_errors(&mut state.error, err);
66                    break Status::Success(state.output(), state.error());
67                }
68                Status::Failure(err, false) => {
69                    merge_errors(&mut state.error, Some(err));
70                    break Status::Failure(state.error().unwrap(), false);
71                }
72                Status::Failure(err, true) => break Status::Failure(err, true),
73            }
74        }))
75    }
76}