somen/parser/combinator/
skip.rs1use 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, EitherState};
8use crate::parser::Parser;
9use crate::stream::Positioned;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct Skip<P, Q> {
16 inner: P,
17 skipped: Q,
18}
19
20impl<P, Q> Skip<P, Q> {
21 #[inline]
23 pub fn new(inner: P, skipped: Q) -> Self {
24 Self { inner, skipped }
25 }
26
27 #[inline]
29 pub fn into_inner(self) -> (P, Q) {
30 (self.inner, self.skipped)
31 }
32}
33
34crate::parser_state! {
35 pub struct SkipState<I, P: Parser, Q: Parser> {
36 inner: EitherState<P::State, Q::State>,
37 #[opt]
38 output: P::Output,
39 error: Option<Error<I::Locator>>,
40 }
41}
42
43impl<P, Q, I> Parser<I> for Skip<P, Q>
44where
45 P: Parser<I>,
46 Q: Parser<I>,
47 I: Positioned + ?Sized,
48{
49 type Output = P::Output;
50 type State = SkipState<I, P, Q>;
51
52 fn poll_parse(
53 &mut self,
54 mut input: Pin<&mut I>,
55 cx: &mut Context<'_>,
56 state: &mut Self::State,
57 ) -> PolledResult<Self::Output, I> {
58 if let EitherState::Left(inner) = &mut state.inner {
59 match ready!(self.inner.poll_parse(input.as_mut(), cx, inner)?) {
60 Status::Success(val, err) => {
61 state.output = Some(val);
62 state.inner = EitherState::new_right();
63 state.error = err;
64 }
65 failure => return Poll::Ready(Ok(failure)),
66 }
67 }
68
69 self.skipped
70 .poll_parse(input, cx, state.inner.right())
71 .map_ok(|status| match status {
72 Status::Success(_, err) => {
73 merge_errors(&mut state.error, err);
74 Status::Success(state.output(), state.error())
75 }
76 Status::Failure(err, false) => {
77 merge_errors(&mut state.error, Some(err));
78 Status::Failure(state.error().unwrap(), false)
79 }
80 Status::Failure(err, true) => Status::Failure(err, true),
81 })
82 }
83}
84
85crate::parser_state! {
86 pub struct SkipIterableState<I, P: IterableParser, Q: Parser> {
87 inner: EitherState<P::State, Q::State>,
88 error: Option<Error<I::Locator>>,
89 }
90}
91
92impl<P, Q, I> IterableParser<I> for Skip<P, Q>
93where
94 P: IterableParser<I>,
95 Q: Parser<I>,
96 I: Positioned + ?Sized,
97{
98 type Item = P::Item;
99 type State = SkipIterableState<I, P, Q>;
100
101 fn poll_parse_next(
102 &mut self,
103 mut input: Pin<&mut I>,
104 cx: &mut Context<'_>,
105 state: &mut Self::State,
106 ) -> PolledResult<Option<Self::Item>, I> {
107 if let EitherState::Left(inner) = &mut state.inner {
108 match ready!(self.inner.poll_parse_next(input.as_mut(), cx, inner))? {
109 Status::Success(None, err) => {
110 state.inner = EitherState::new_right();
111 state.error = err;
112 }
113 res => return Poll::Ready(Ok(res)),
114 }
115 }
116
117 self.skipped
118 .poll_parse(input, cx, state.inner.right())
119 .map_ok(|status| match status {
120 Status::Success(_, err) => {
121 merge_errors(&mut state.error, err);
122 Status::Success(None, state.error())
123 }
124 Status::Failure(err, false) => {
125 merge_errors(&mut state.error, Some(err));
126 Status::Failure(state.error().unwrap(), false)
127 }
128 Status::Failure(err, true) => Status::Failure(err, true),
129 })
130 }
131
132 #[inline]
133 fn size_hint(&self) -> (usize, Option<usize>) {
134 self.inner.size_hint()
135 }
136}