utils/parser/
iterator.rs

1use crate::input::InputError;
2use crate::parser::{ParseState, Parser};
3use std::iter::FusedIterator;
4
5/// An iterator that lazily parses the input using the provided parser.
6///
7/// See [`Parser::parse_iterator`].
8#[derive(Copy, Clone)]
9#[must_use = "iterators are lazy and do nothing unless consumed"]
10pub struct ParserIterator<'a, P> {
11    pub(super) input: &'a str,
12    pub(super) remaining: &'a [u8],
13    pub(super) parser: P,
14}
15
16impl<'a, P: Parser<'a>> Iterator for ParserIterator<'a, P> {
17    type Item = Result<P::Output, InputError>;
18
19    #[inline]
20    fn next(&mut self) -> Option<Self::Item> {
21        if self.remaining.is_empty() {
22            return None;
23        }
24
25        // Don't use parse_once so errors are reported at the correct position in the overall input.
26        let mut state = ParseState::default();
27        if let Ok((v, remaining)) =
28            self.parser
29                .parse_ctx(self.remaining, &mut state, &mut false, false)
30        {
31            self.remaining = remaining;
32            Some(Ok(v))
33        } else {
34            self.remaining = &[]; // Ensure future calls return None
35            Some(Err(state.into_input_error(self.input)))
36        }
37    }
38}
39
40impl<'a, P: Parser<'a>> FusedIterator for ParserIterator<'a, P> {}
41
42impl<'a, P: Parser<'a>> ParserIterator<'a, P> {
43    /// Returns the remaining input.
44    ///
45    /// # Examples
46    /// ```
47    /// # use utils::input::InputError;
48    /// # use utils::parser::{self, Parser};
49    /// let mut iterator = parser::u32()
50    ///     .with_eol()
51    ///     .parse_iterator("12\n34\n56\n78");
52    /// assert_eq!(iterator.next().unwrap().unwrap(), 12);
53    /// assert_eq!(iterator.next().unwrap().unwrap(), 34);
54    /// assert_eq!(iterator.remaining(), b"56\n78");
55    /// ```
56    #[inline]
57    pub fn remaining(&self) -> &'a [u8] {
58        self.remaining
59    }
60}
61
62/// An iterator which returns successful parse outputs only, skipping over errors.
63///
64/// See [`Parser::matches_iterator`].
65#[derive(Copy, Clone)]
66#[must_use = "iterators are lazy and do nothing unless consumed"]
67pub struct ParserMatchesIterator<'a, P> {
68    pub(super) remaining: &'a [u8],
69    pub(super) parser: P,
70}
71
72impl<'a, P: Parser<'a>> Iterator for ParserMatchesIterator<'a, P> {
73    type Item = P::Output;
74
75    #[inline]
76    fn next(&mut self) -> Option<Self::Item> {
77        while !self.remaining.is_empty() {
78            // Use parse_ctx to avoid constructing full InputError instances which is expensive
79            if let Ok((v, remaining)) = self.parser.parse_ctx(
80                self.remaining,
81                &mut ParseState::default(),
82                &mut false,
83                false,
84            ) {
85                self.remaining = remaining;
86                return Some(v);
87            }
88            self.remaining = &self.remaining[1..];
89        }
90        None
91    }
92}
93
94impl<'a, P: Parser<'a>> FusedIterator for ParserMatchesIterator<'a, P> {}
95
96impl<'a, P: Parser<'a>> ParserMatchesIterator<'a, P> {
97    /// Returns the remaining input.
98    ///
99    /// # Examples
100    /// ```
101    /// # use utils::input::InputError;
102    /// # use utils::parser::{self, Parser};
103    /// let mut iterator = parser::u32()
104    ///     .matches_iterator("abc123d456e7xyz");
105    /// assert_eq!(iterator.next().unwrap(), 123);
106    /// assert_eq!(iterator.next().unwrap(), 456);
107    /// assert_eq!(iterator.remaining(), b"e7xyz");
108    /// ```
109    #[inline]
110    pub fn remaining(&self) -> &'a [u8] {
111        self.remaining
112    }
113}