smart_string/str_stack/
iter.rs1use crate::StrStack;
2
3pub struct StrStackIter<'a> {
5 stack: &'a StrStack,
6 index: usize,
7 back_index: usize,
8}
9
10impl<'a> StrStackIter<'a> {
11 #[inline]
12 pub fn new(stack: &'a StrStack) -> Self {
13 Self {
14 back_index: stack.ends_as_slice().len(),
15 stack,
16 index: 0,
17 }
18 }
19
20 #[inline]
21 fn bounds(&self, index: usize) -> (usize, usize) {
22 let ends = self.stack.ends_as_slice();
23 let start = if index > 0 {
24 ends[index - 1] as usize
25 } else {
26 0
27 };
28 let end = ends[index] as usize;
29 (start, end)
30 }
31}
32
33impl<'a> Iterator for StrStackIter<'a> {
34 type Item = &'a str;
35
36 #[inline]
37 fn next(&mut self) -> Option<Self::Item> {
38 if self.index >= self.back_index {
39 return None;
40 }
41 let (begin, end) = self.bounds(self.index);
42 self.index += 1;
43 Some(unsafe { self.stack.get_unchecked_internal(begin, end) })
46 }
47
48 #[inline]
49 fn size_hint(&self) -> (usize, Option<usize>) {
50 let len = self.len();
51 (len, Some(len))
52 }
53}
54
55impl<'a> DoubleEndedIterator for StrStackIter<'a> {
56 #[inline]
57 fn next_back(&mut self) -> Option<Self::Item> {
58 if self.back_index <= self.index {
59 return None;
60 }
61 self.back_index -= 1;
62 let (begin, end) = self.bounds(self.back_index);
63 Some(unsafe { self.stack.get_unchecked_internal(begin, end) })
65 }
66}
67
68impl<'a> ExactSizeIterator for StrStackIter<'a> {
69 #[inline]
70 fn len(&self) -> usize {
71 self.back_index - self.index
72 }
73}
74
75impl<'a> std::iter::FusedIterator for StrStackIter<'a> {}
76
77impl<'a> IntoIterator for &'a StrStack {
78 type Item = <StrStackIter<'a> as Iterator>::Item;
79 type IntoIter = StrStackIter<'a>;
80
81 #[inline]
82 fn into_iter(self) -> Self::IntoIter {
83 StrStackIter::new(self)
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_iter() {
93 let mut stack = StrStack::new();
94
95 stack.push("123");
96 stack.push("456");
97 stack.push("789");
98
99 let mut iter = StrStackIter::new(&stack);
100 assert_eq!(iter.next(), Some("123"));
101 assert_eq!(iter.next(), Some("456"));
102 assert_eq!(iter.next(), Some("789"));
103 assert_eq!(iter.next(), None);
104 assert_eq!(iter.next(), None);
105 }
106
107 #[test]
108 fn test_iter_empty() {
109 let stack = StrStack::new();
110
111 let mut iter = StrStackIter::new(&stack);
112 assert_eq!(iter.next(), None);
113 assert_eq!(iter.next(), None);
114 }
115
116 #[test]
117 fn test_exact_size_len_and_size_hint_decrease() {
118 let mut stack = StrStack::new();
119 stack.push("a");
120 stack.push("bb");
121 stack.push("ccc");
122
123 let mut it = stack.iter();
124 assert_eq!(it.len(), 3);
125 assert_eq!(it.size_hint(), (3, Some(3)));
126
127 assert_eq!(it.next(), Some("a"));
128 assert_eq!(it.len(), 2);
129 assert_eq!(it.size_hint(), (2, Some(2)));
130
131 assert_eq!(it.next(), Some("bb"));
132 assert_eq!(it.len(), 1);
133 assert_eq!(it.size_hint(), (1, Some(1)));
134
135 assert_eq!(it.next(), Some("ccc"));
136 assert_eq!(it.len(), 0);
137 assert_eq!(it.size_hint(), (0, Some(0)));
138
139 assert_eq!(it.next(), None);
140 assert_eq!(it.len(), 0);
141 assert_eq!(it.size_hint(), (0, Some(0)));
142 }
143
144 #[test]
145 fn test_iter_reverse() {
146 let mut stack = StrStack::new();
147 stack.push("a");
148 stack.push("b");
149 stack.push("c");
150
151 let collected: Vec<&str> = stack.iter().rev().collect();
152 assert_eq!(collected, vec!["c", "b", "a"]);
153 }
154
155 #[test]
156 fn test_iter_double_ended_meet_in_middle() {
157 let mut stack = StrStack::new();
158 stack.push("a");
159 stack.push("b");
160 stack.push("c");
161 stack.push("d");
162
163 let mut it = stack.iter();
164 assert_eq!(it.next(), Some("a"));
165 assert_eq!(it.next_back(), Some("d"));
166 assert_eq!(it.next(), Some("b"));
167 assert_eq!(it.next_back(), Some("c"));
168 assert_eq!(it.next(), None);
169 assert_eq!(it.next_back(), None);
170 }
171
172 #[test]
173 fn test_iter_fused() {
174 let mut stack = StrStack::new();
175 stack.push("x");
176
177 let mut it = stack.iter();
178 assert_eq!(it.next(), Some("x"));
179 assert_eq!(it.next(), None);
180 assert_eq!(it.next(), None);
181 assert_eq!(it.next(), None);
182 }
183}