somen/parser/iterable/combinator/
flatten.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::stream::Positioned;
9
10/// A parser for method [`flatten`].
11///
12/// [`flatten`]: crate::parser::iterable::IterableParserExt::flatten
13#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct Flatten<P> {
15    inner: P,
16}
17
18impl<P> Flatten<P> {
19    /// Creates a new instance.
20    #[inline]
21    pub fn new(inner: P) -> Self {
22        Self { inner }
23    }
24
25    /// Extracts the inner parser.
26    #[inline]
27    pub fn into_inner(self) -> P {
28        self.inner
29    }
30}
31
32crate::parser_state! {
33    pub struct FlattenState<I, P: IterableParser; T> {
34        inner: P::State,
35        iter: Option<T>,
36        error: Option<Error<I::Locator>>,
37    }
38}
39
40impl<P, I> IterableParser<I> for Flatten<P>
41where
42    P: IterableParser<I>,
43    P::Item: IntoIterator,
44    I: Positioned + ?Sized,
45{
46    type Item = <P::Item as IntoIterator>::Item;
47    type State = FlattenState<I, P, <P::Item as IntoIterator>::IntoIter>;
48
49    fn poll_parse_next(
50        &mut self,
51        mut input: Pin<&mut I>,
52        cx: &mut Context<'_>,
53        state: &mut Self::State,
54    ) -> PolledResult<Option<Self::Item>, I> {
55        Poll::Ready(Ok(loop {
56            if let Some(iter) = &mut state.iter {
57                if let Some(val) = iter.next() {
58                    break Status::Success(Some(val), state.error());
59                }
60            }
61
62            match ready!(self
63                .inner
64                .poll_parse_next(input.as_mut(), cx, &mut state.inner)?)
65            {
66                Status::Success(Some(iter), err) => {
67                    state.iter = Some(iter.into_iter());
68                    merge_errors(&mut state.error, err);
69                }
70                Status::Success(None, err) => {
71                    merge_errors(&mut state.error, err);
72                    break Status::Success(None, state.error());
73                }
74                Status::Failure(err, false) => {
75                    merge_errors(&mut state.error, Some(err));
76                    break Status::Failure(state.error().unwrap(), false);
77                }
78                Status::Failure(err, true) => break Status::Failure(err, true),
79            }
80        }))
81    }
82}