utils/parser/
iterator.rs

1use crate::input::InputError;
2use crate::parser::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> Iterator for ParserIterator<'a, P> {
17    type Item = Result<P::Output<'a>, InputError>;
18
19    #[inline]
20    fn next(&mut self) -> Option<Self::Item> {
21        if self.remaining.is_empty() {
22            return None;
23        }
24
25        match self.parser.parse(self.remaining) {
26            Ok((v, remaining)) => {
27                self.remaining = remaining;
28                Some(Ok(v))
29            }
30            Err((err, remaining)) => {
31                self.remaining = &[]; // Ensure future calls return None
32                Some(Err(InputError::new(self.input, remaining, err)))
33            }
34        }
35    }
36}
37
38impl<P: Parser> FusedIterator for ParserIterator<'_, P> {}
39
40/// An iterator which returns successful parse outputs only, skipping over errors.
41///
42/// See [`Parser::matches_iterator`].
43#[derive(Copy, Clone)]
44#[must_use = "iterators are lazy and do nothing unless consumed"]
45pub struct ParserMatchesIterator<'a, P> {
46    pub(super) remaining: &'a [u8],
47    pub(super) parser: P,
48}
49
50impl<'a, P: Parser> Iterator for ParserMatchesIterator<'a, P> {
51    type Item = P::Output<'a>;
52
53    #[inline]
54    fn next(&mut self) -> Option<Self::Item> {
55        while !self.remaining.is_empty() {
56            if let Ok((v, remaining)) = self.parser.parse(self.remaining) {
57                self.remaining = remaining;
58                return Some(v);
59            }
60            self.remaining = &self.remaining[1..];
61        }
62        None
63    }
64}
65
66impl<P: Parser> FusedIterator for ParserMatchesIterator<'_, P> {}