1use crate::collex::CollexField;
2use crate::{Collexetable, Field, FieldCollex, FieldValue, RawField};
3
4enum IterStackItem<'a, E, V>
7where
8 E: Collexetable<V>,
9 V: FieldValue,
10{
11 Outer(std::slice::Iter<'a, CollexField<E, V>>),
13 Inner(Iter<'a, E, V>),
15}
16
17pub struct Iter<'a, E, V>
19where
20 E: Collexetable<V>,
21 V: FieldValue,
22{
23 stack: Vec<IterStackItem<'a, E, V>>,
25}
26
27impl<'a, E, V> Iter<'a, E, V>
28where
29 E: Collexetable<V>,
30 V: FieldValue,
31{
32 pub(crate) fn new(collex: &'a FieldCollex<E, V>) -> Self {
34 Self {
35 stack: vec![IterStackItem::Outer(collex.items.iter())],
36 }
37 }
38}
39
40
41impl<E, V> FieldCollex<E, V>
42where
43 E: Collexetable<V>,
44 V: FieldValue,
45{
46 pub fn iter(&self) -> Iter<'_, E, V> {
48 Iter {
49 stack: vec![IterStackItem::Outer(self.items.iter())],
50 }
51 }
52}
53
54impl<'a, E, V> Iterator for Iter<'a, E, V>
56where
57 E: Collexetable<V>,
58 V: FieldValue,
59{
60 type Item = &'a E;
61
62 fn next(&mut self) -> Option<Self::Item> {
63 while let Some(mut iter_item) = self.stack.pop() {
65 match &mut iter_item {
66 IterStackItem::Outer(outer_iter) => {
68 while let Some(field) = outer_iter.next() {
69 match field {
70 RawField::Thing((_, field)) => match field {
71 Field::Elem(e) => {
73 self.stack.push(iter_item);
75 return Some(e);
76 }
77 Field::Collex(collex) => {
79 self.stack.push(iter_item);
81 self.stack.push(IterStackItem::Inner(collex.iter()));
83 break;
85 }
86 },
87 _ => continue,
89 }
90 }
91 }
93 IterStackItem::Inner(inner_iter) => {
95 if let Some(item) = inner_iter.next() {
96 self.stack.push(iter_item);
98 return Some(item);
99 }
100 }
102 }
103 }
104
105 None
107 }
108}
109
110#[derive(Debug)]
111pub enum IntoIterStackItem<E, V>
112where
113 E: Collexetable<V>,
114 V: FieldValue,
115{
116 Outer(std::vec::IntoIter<CollexField<E, V>>),
118 Inner(IntoIter<E, V>),
120}
121
122#[derive(Debug)]
123pub struct IntoIter<E, V>
124where
125 E: Collexetable<V>,
126 V: FieldValue,
127{
128 stack: Vec<IntoIterStackItem<E, V>>,
129}
130
131impl<E, V> IntoIter<E, V>
132where
133 E: Collexetable<V>,
134 V: FieldValue,
135{
136 pub(crate) fn new(collex: FieldCollex<E, V>) -> Self {
137 let outer_iter = collex.items.into_iter();
139 Self {
140 stack: vec![IntoIterStackItem::Outer(outer_iter)],
141 }
142 }
143}
144
145impl<E, V> Iterator for IntoIter<E, V>
147where
148 E: Collexetable<V>,
149 V: FieldValue,
150{
151 type Item = E;
152
153 fn next(&mut self) -> Option<Self::Item> {
154 while let Some(mut iter_item) = self.stack.pop() {
156 match &mut iter_item {
157 IntoIterStackItem::Outer(outer_iter) => {
158 while let Some(field) = outer_iter.next() {
160 match field {
161 RawField::Thing((_, field_in)) => match field_in {
162 Field::Elem(e) => {
164 self.stack.push(IntoIterStackItem::Outer(std::mem::take(outer_iter)));
166 return Some(e);
167 }
168 Field::Collex(collex) => {
170 self.stack.push(IntoIterStackItem::Outer(std::mem::take(outer_iter)));
172 self.stack.push(IntoIterStackItem::Inner(IntoIter::new(collex)));
174 break;
176 }
177 },
178 RawField::Prev(_) | RawField::Among(_, _) | RawField::Next(_) | RawField::Void => continue,
180 }
181 }
182 }
184 IntoIterStackItem::Inner(inner_iter) => {
185 if let Some(item) = inner_iter.next() {
187 self.stack.push(iter_item);
189 return Some(item);
190 }
191 }
193 }
194 }
195 None
197 }
198}
199
200impl<E, V> IntoIterator for FieldCollex<E, V>
202where
203 E: Collexetable<V>,
204 V: FieldValue,
205{
206 type Item = E;
207 type IntoIter = IntoIter<E, V>;
208
209 fn into_iter(self) -> Self::IntoIter {
210 IntoIter::new(self)
211 }
212}
213
214impl<'a, E, V> IntoIterator for &'a FieldCollex<E, V>
215where
216 E: Collexetable<V>,
217 V: FieldValue,
218{
219 type Item = &'a E;
220 type IntoIter = Iter<'a, E, V>;
221
222 fn into_iter(self) -> Self::IntoIter {
223 Iter::new(self)
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use super::*;
230 use span_core::Span;
231
232 #[derive(Debug, PartialEq, Eq, Ord, PartialOrd)]
234 #[derive(Clone)]
235struct TestElem(u32);
236
237 impl Collexetable<u32> for TestElem {
238 fn collexate(&self) -> u32 {
239 self.0
240 }
241
242 fn collexate_ref(&self) -> &u32 {
243 &self.0
244 }
245
246 fn collexate_mut(&mut self) -> &mut u32 {
247 &mut self.0
248 }
249 }
250 #[test]
251 fn test_iter() {
252 let span = Span::new_finite(0u32, 100u32);
253 let unit = 20u32;
254 let elems = vec![TestElem(5), TestElem(15), TestElem(25), TestElem(55)];
255 let collex = FieldCollex::<TestElem, u32>::with_elements(span, unit, elems).unwrap();
256
257 let collected: Vec<_> = collex.iter().cloned().collect();
259 assert_eq!(collected, vec![TestElem(5), TestElem(15), TestElem(25), TestElem(55)]);
260
261 let mut values = Vec::new();
263 for elem in &collex {
264 values.push(elem.0);
265 }
266 assert_eq!(values, vec![5, 15, 25, 55]);
267
268 let empty_collex = FieldCollex::<TestElem, u32>::new(Span::new_finite(0u32, 100u32), 10u32).unwrap();
270 assert!(empty_collex.iter().next().is_none());
271 }
272}