1use std::{iter::Zip, mem::take, slice::Iter, str::Chars};
2
3use crate::{view::CodeView, CodeSpan};
4
5#[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}