code_span/view/
iter.rs

1use std::{iter::Zip, mem::take, slice::Iter, str::Chars};
2
3use crate::{view::CodeView, CodeSpan};
4
5/// # Arguments
6///
7/// * `text`:
8/// * `default`:
9///
10/// returns: TextView<T>
11///
12/// # Examples
13///
14/// ```
15/// use code_span::CodeView;
16/// ```
17#[derive(Debug)]
18pub struct CodeViewIter<'i, T> {
19    iter: Zip<Iter<'i, Option<T>>, Chars<'i>>,
20    current: Option<T>,
21    buffer: String,
22    run_out: bool,
23}
24
25impl<'i, T> IntoIterator for &'i CodeView<T>
26where
27    T: Clone + PartialEq,
28{
29    type Item = CodeSpan<T>;
30    type IntoIter = CodeViewIter<'i, T>;
31
32    fn into_iter(self) -> Self::IntoIter {
33        let iter = self.info.iter().zip(self.text.chars());
34        CodeViewIter { run_out: false, current: None, iter, buffer: "".to_string() }
35    }
36}
37
38impl<'i, T> Iterator for CodeViewIter<'i, T>
39where
40    T: Clone + PartialEq,
41{
42    type Item = CodeSpan<T>;
43
44    fn next(&mut self) -> Option<Self::Item> {
45        if self.run_out {
46            return None;
47        }
48        while let Some(this) = self.iter.next() {
49            if self.current.eq(this.0) {
50                self.buffer.push(this.1);
51                continue;
52            }
53            else {
54                let out = self.pop_span();
55                self.buffer.push(this.1);
56                self.current = this.0.clone();
57                if out.text.is_empty() {
58                    continue;
59                }
60                else {
61                    return Some(out);
62                }
63            }
64        }
65        self.run_out = true;
66        Some(self.pop_span())
67    }
68}
69
70impl<'i, T> CodeViewIter<'i, T>
71where
72    T: Clone,
73{
74    #[inline]
75    fn pop_span(&mut self) -> CodeSpan<T> {
76        CodeSpan { text: take(&mut self.buffer), info: self.current.clone() }
77    }
78}