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<'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        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<'a, P: Parser<'a>> FusedIterator for ParserIterator<'a, P> {}
39
40impl<'a, P: Parser<'a>> ParserIterator<'a, P> {
41    /// Returns the remaining input.
42    ///
43    /// # Examples
44    /// ```
45    /// # use utils::input::InputError;
46    /// # use utils::parser::{self, Parser};
47    /// let mut iterator = parser::u32()
48    ///     .with_suffix(parser::eol())
49    ///     .parse_iterator("12\n34\n56\n78");
50    /// assert_eq!(iterator.next().unwrap().unwrap(), 12);
51    /// assert_eq!(iterator.next().unwrap().unwrap(), 34);
52    /// assert_eq!(iterator.remaining(), b"56\n78");
53    /// ```
54    #[inline]
55    pub fn remaining(&self) -> &'a [u8] {
56        self.remaining
57    }
58}
59
60/// An iterator which returns successful parse outputs only, skipping over errors.
61///
62/// See [`Parser::matches_iterator`].
63#[derive(Copy, Clone)]
64#[must_use = "iterators are lazy and do nothing unless consumed"]
65pub struct ParserMatchesIterator<'a, P> {
66    pub(super) remaining: &'a [u8],
67    pub(super) parser: P,
68}
69
70impl<'a, P: Parser<'a>> Iterator for ParserMatchesIterator<'a, P> {
71    type Item = P::Output;
72
73    #[inline]
74    fn next(&mut self) -> Option<Self::Item> {
75        while !self.remaining.is_empty() {
76            if let Ok((v, remaining)) = self.parser.parse(self.remaining) {
77                self.remaining = remaining;
78                return Some(v);
79            }
80            self.remaining = &self.remaining[1..];
81        }
82        None
83    }
84}
85
86impl<'a, P: Parser<'a>> FusedIterator for ParserMatchesIterator<'a, P> {}
87
88impl<'a, P: Parser<'a>> ParserMatchesIterator<'a, P> {
89    /// Returns the remaining input.
90    ///
91    /// # Examples
92    /// ```
93    /// # use utils::input::InputError;
94    /// # use utils::parser::{self, Parser};
95    /// let mut iterator = parser::u32()
96    ///     .matches_iterator("abc123d456e7xyz");
97    /// assert_eq!(iterator.next().unwrap(), 123);
98    /// assert_eq!(iterator.next().unwrap(), 456);
99    /// assert_eq!(iterator.remaining(), b"e7xyz");
100    /// ```
101    #[inline]
102    pub fn remaining(&self) -> &'a [u8] {
103        self.remaining
104    }
105}