smart_string/str_stack/
iter.rs1use crate::StrStack;
2
3#[derive(Clone, Copy, Debug)]
4struct Cursor {
5 index: usize,
6 begin: usize,
7 end: usize,
8}
9
10impl Cursor {
11 #[inline]
12 pub fn new(index: usize, begin: usize, end: usize) -> Self {
13 Self { index, begin, end }
14 }
15}
16
17pub struct StrStackIter<'a> {
18 stack: &'a StrStack,
19 next: Option<Cursor>,
20}
21
22impl<'a> StrStackIter<'a> {
23 #[inline]
24 pub fn new(stack: &'a StrStack) -> Self {
25 let next = stack
26 .ends
27 .first()
28 .copied()
29 .map(|end| Cursor::new(0, 0, end));
30 Self { stack, next }
31 }
32}
33
34impl<'a> Iterator for StrStackIter<'a> {
35 type Item = &'a str;
36
37 #[inline]
38 fn next(&mut self) -> Option<Self::Item> {
39 let Cursor { index, begin, end } = self.next?;
40 let next_index = index + 1;
41 self.next = self
42 .stack
43 .ends
44 .get(next_index)
45 .copied()
46 .map(|next_end| Cursor::new(next_index, end, next_end));
47 Some(unsafe { self.stack.get_unchecked_internal(begin, end) })
50 }
51
52 #[inline]
53 fn size_hint(&self) -> (usize, Option<usize>) {
54 let len = self.len();
55 (len, Some(len))
56 }
57}
58
59impl<'a> ExactSizeIterator for StrStackIter<'a> {
60 #[inline]
61 fn len(&self) -> usize {
62 self.next
63 .map(|c| self.stack.ends.len() - c.index)
64 .unwrap_or(0)
65 }
66}
67
68impl<'a> IntoIterator for &'a StrStack {
69 type Item = <StrStackIter<'a> as Iterator>::Item;
70 type IntoIter = StrStackIter<'a>;
71
72 #[inline]
73 fn into_iter(self) -> Self::IntoIter {
74 StrStackIter::new(self)
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_iter() {
84 let mut stack = StrStack::new();
85
86 stack.push("123");
87 stack.push("456");
88 stack.push("789");
89
90 let mut iter = StrStackIter::new(&stack);
91 assert_eq!(iter.next(), Some("123"));
92 assert_eq!(iter.next(), Some("456"));
93 assert_eq!(iter.next(), Some("789"));
94 assert_eq!(iter.next(), None);
95 assert_eq!(iter.next(), None);
96 }
97
98 #[test]
99 fn test_iter_empty() {
100 let stack = StrStack::new();
101
102 let mut iter = StrStackIter::new(&stack);
103 assert_eq!(iter.next(), None);
104 assert_eq!(iter.next(), None);
105 }
106
107 #[test]
108 fn test_exact_size_len_and_size_hint_decrease() {
109 let mut stack = StrStack::new();
110 stack.push("a");
111 stack.push("bb");
112 stack.push("ccc");
113
114 let mut it = stack.iter();
115 assert_eq!(it.len(), 3);
116 assert_eq!(it.size_hint(), (3, Some(3)));
117
118 assert_eq!(it.next(), Some("a"));
119 assert_eq!(it.len(), 2);
120 assert_eq!(it.size_hint(), (2, Some(2)));
121
122 assert_eq!(it.next(), Some("bb"));
123 assert_eq!(it.len(), 1);
124 assert_eq!(it.size_hint(), (1, Some(1)));
125
126 assert_eq!(it.next(), Some("ccc"));
127 assert_eq!(it.len(), 0);
128 assert_eq!(it.size_hint(), (0, Some(0)));
129
130 assert_eq!(it.next(), None);
131 assert_eq!(it.len(), 0);
132 assert_eq!(it.size_hint(), (0, Some(0)));
133 }
134}