somen/parser/iterable/generator/
sep_by_end.rs1use 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#[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 #[inline]
25 pub fn new(inner: P, sep: Q, range: R) -> Self {
26 Self { inner, sep, range }
27 }
28
29 #[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 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}