string_sections/
section_iter.rs

1use std::{iter::FusedIterator, str::Lines};
2
3use crate::{section_span::SectionSpan, SectionFinder};
4
5pub use super::LineSpan;
6
7#[derive(Clone)]
8pub struct SectionIter<'a, F: SectionFinder> {
9    pub(crate) text: &'a str,
10    pub(crate) iter: Lines<'a>,
11    pub(crate) finder: F,
12}
13
14impl<'a, F: SectionFinder> SectionIter<'a, F> {
15    fn next_start(&mut self) -> Option<LineSpan<'a>> {
16        while let Some(line) = self.iter.next() {
17            let line = LineSpan::new(self.text, line);
18
19            if self.finder.is_start(&line) {
20                return Some(line);
21            }
22        }
23        None
24    }
25
26    fn forward_to_end(&mut self, section: &mut SectionSpan<'a>) -> bool {
27        while let Some(line) = self.iter.next() {
28            section.end_line = LineSpan::new(self.text, line);
29            if self.finder.is_end(&section) {
30                return true;
31            }
32        }
33        false
34    }
35}
36
37impl<'a, F: SectionFinder> Iterator for SectionIter<'a, F> {
38    type Item = SectionSpan<'a>;
39
40    fn next(&mut self) -> Option<Self::Item> {
41        if let Some(start_line) = self.next_start() {
42            let mut section = SectionSpan {
43                start_line,
44                end_line: start_line,
45            };
46            self.forward_to_end(&mut section);
47            Some(section)
48        } else {
49            None
50        }
51    }
52}
53
54impl<'a, F: SectionFinder> FusedIterator for SectionIter<'a, F> {}