somen/parser/iterable/generator/
sep_by_end.rs

1use core::ops::{Bound, RangeBounds};
2use core::pin::Pin;
3use core::task::{Context, Poll};
4use futures_core::ready;
5
6use crate::error::{Error, PolledResult, Status};
7use crate::parser::utils::{merge_errors, EitherState};
8use crate::parser::Parser;
9use crate::prelude::IterableParser;
10use crate::stream::Input;
11
12/// A iterable parser generated from method [`sep_by_end`].
13///
14/// [`sep_by_end`]: crate::parser::ParserExt::sep_by_end
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct SepByEnd<P, Q, R> {
17    inner: P,
18    sep: Q,
19    range: R,
20}
21
22impl<P, Q, R> SepByEnd<P, Q, R> {
23    /// Creates a new instance.
24    #[inline]
25    pub fn new(inner: P, sep: Q, range: R) -> Self {
26        Self { inner, sep, range }
27    }
28
29    /// Extracts the inner parser.
30    #[inline]
31    pub fn into_inner(self) -> P {
32        self.inner
33    }
34}
35
36crate::parser_state! {
37    pub struct SepByEndState<I: Input, P: Parser, Q: Parser> {
38        inner: EitherState<P::State, Q::State>,
39        #[opt(try_set = set_marker)]
40        marker: I::Marker,
41        #[opt(set = set_start)]
42        start: I::Locator,
43        #[opt]
44        output: P::Output,
45        error: Option<Error<I::Locator>>,
46        end: bool,
47        count: usize,
48    }
49}
50
51impl<P, Q, R, I> IterableParser<I> for SepByEnd<P, Q, R>
52where
53    P: Parser<I>,
54    Q: Parser<I>,
55    R: RangeBounds<usize>,
56    I: Input + ?Sized,
57{
58    type Item = P::Output;
59    type State = SepByEndState<I, P, Q>;
60
61    fn poll_parse_next(
62        &mut self,
63        mut input: Pin<&mut I>,
64        cx: &mut Context<'_>,
65        state: &mut Self::State,
66    ) -> PolledResult<Option<Self::Item>, I> {
67        // Return `None` if the number of items already reached `end_bound`.
68        if match self.range.end_bound() {
69            Bound::Included(i) => state.count + 1 > *i,
70            Bound::Excluded(i) => state.count + 1 >= *i,
71            Bound::Unbounded => false,
72        } || state.end
73        {
74            return Poll::Ready(Ok(Status::Success(None, None)));
75        }
76
77        state.set_marker(|| input.as_mut().mark())?;
78        state.set_start(|| input.position());
79
80        if let EitherState::Left(inner) = &mut state.inner {
81            match ready!(self.inner.poll_parse(input.as_mut(), cx, inner)?) {
82                Status::Success(val, err) => {
83                    input.as_mut().drop_marker(state.marker())?;
84                    state.marker = Some(input.as_mut().mark()?);
85                    state.start = Some(input.position());
86                    state.output = Some(val);
87                    state.inner = EitherState::new_right();
88                    state.error = err;
89                }
90                Status::Failure(err, false) if err.rewindable(&state.start()) => {
91                    input.rewind(state.marker())?;
92                    return Poll::Ready(Ok(Status::Success(None, Some(err))));
93                }
94                Status::Failure(err, exclusive) => {
95                    input.drop_marker(state.marker())?;
96                    return Poll::Ready(Ok(Status::Failure(err, exclusive)));
97                }
98            }
99        }
100
101        Poll::Ready(Ok(
102            match ready!(self
103                .sep
104                .poll_parse(input.as_mut(), cx, state.inner.right())?)
105            {
106                Status::Success(_, err) => {
107                    input.drop_marker(state.marker())?;
108                    state.start = None;
109                    state.count += 1;
110                    state.inner = EitherState::new_left();
111                    merge_errors(&mut state.error, err);
112                    Status::Success(Some(state.output()), state.error())
113                }
114                Status::Failure(err, false)
115                    if err.rewindable(&state.start())
116                        && self.range.contains(&(state.count + 1)) =>
117                {
118                    input.rewind(state.marker())?;
119                    merge_errors(&mut state.error, Some(err));
120                    state.end = true;
121                    Status::Success(Some(state.output()), state.error())
122                }
123                Status::Failure(err, false) => {
124                    input.drop_marker(state.marker())?;
125                    merge_errors(&mut state.error, Some(err));
126                    Status::Failure(state.error().unwrap(), false)
127                }
128                Status::Failure(err, true) => {
129                    input.drop_marker(state.marker())?;
130                    Status::Failure(err, true)
131                }
132            },
133        ))
134    }
135
136    fn size_hint(&self) -> (usize, Option<usize>) {
137        let start = match self.range.start_bound() {
138            Bound::Included(i) => *i,
139            Bound::Excluded(i) => *i + 1,
140            Bound::Unbounded => 0,
141        };
142
143        let end = match self.range.end_bound() {
144            Bound::Included(i) => Some(*i),
145            Bound::Excluded(i) => Some(*i - 1),
146            Bound::Unbounded => None,
147        };
148
149        (start, end)
150    }
151}