tabled/settings/object/
iterator.rs

1//! This module contains an [`ObjectIterator`].
2
3use core::marker::PhantomData;
4
5use crate::grid::config::Entity;
6use crate::settings::object::Object;
7
8/// A utility trait helps to modify an [`Object`],
9/// by various functions.
10pub trait ObjectIterator<R>: Object<R> {
11    /// Skip N entities.
12    fn skip(self, n: usize) -> SkipObject<Self, R>
13    where
14        Self: Sized,
15    {
16        SkipObject::new(self, n)
17    }
18
19    /// Make a step for an iteration of entities.
20    fn step_by(self, n: usize) -> StepByObject<Self, R>
21    where
22        Self: Sized,
23    {
24        StepByObject::new(self, n)
25    }
26
27    /// Use a filter while iterating over entities.
28    fn filter<F>(self, predicate: F) -> FilterObject<Self, F, R>
29    where
30        Self: Sized,
31        F: Fn(Entity) -> bool,
32    {
33        FilterObject::new(self, predicate)
34    }
35}
36
37impl<T, R> ObjectIterator<R> for T where T: Object<R> {}
38
39/// Skip object for any [`Object`].
40#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
41pub struct SkipObject<O, R> {
42    obj: O,
43    n: usize,
44    _records: PhantomData<R>,
45}
46
47impl<O, R> SkipObject<O, R> {
48    fn new(obj: O, n: usize) -> Self {
49        Self {
50            obj,
51            n,
52            _records: PhantomData,
53        }
54    }
55}
56
57impl<O, R> Object<R> for SkipObject<O, R>
58where
59    O: Object<R>,
60{
61    type Iter = SkipObjectIter<O::Iter>;
62
63    fn cells(&self, records: &R) -> Self::Iter {
64        SkipObjectIter::new(self.obj.cells(records), self.n)
65    }
66}
67
68/// Skip object iterator for any [`Object`].
69#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
70pub struct SkipObjectIter<I> {
71    iter: I,
72    n: usize,
73}
74
75impl<I> SkipObjectIter<I> {
76    fn new(iter: I, n: usize) -> Self {
77        Self { iter, n }
78    }
79}
80
81impl<I> Iterator for SkipObjectIter<I>
82where
83    I: Iterator,
84{
85    type Item = I::Item;
86
87    fn next(&mut self) -> Option<Self::Item> {
88        while self.n > 0 {
89            self.n -= 1;
90            let _ = self.iter.next()?;
91        }
92
93        self.iter.next()
94    }
95}
96
97/// Step object for any [`Object`].
98#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
99pub struct StepByObject<O, R> {
100    obj: O,
101    n: usize,
102    _records: PhantomData<R>,
103}
104
105impl<O, R> StepByObject<O, R> {
106    fn new(obj: O, n: usize) -> Self {
107        Self {
108            obj,
109            n,
110            _records: PhantomData,
111        }
112    }
113}
114
115impl<O, R> Object<R> for StepByObject<O, R>
116where
117    O: Object<R>,
118{
119    type Iter = StepByObjectIter<O::Iter>;
120
121    fn cells(&self, records: &R) -> Self::Iter {
122        StepByObjectIter::new(self.obj.cells(records), self.n)
123    }
124}
125
126/// Step object iterator for any [`Object`].
127#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
128pub struct StepByObjectIter<I> {
129    iter: I,
130    step: usize,
131    end: bool,
132}
133
134impl<I> StepByObjectIter<I> {
135    fn new(iter: I, step: usize) -> Self {
136        let end = step == 0;
137
138        Self { iter, step, end }
139    }
140}
141
142impl<I> Iterator for StepByObjectIter<I>
143where
144    I: Iterator,
145{
146    type Item = I::Item;
147
148    fn next(&mut self) -> Option<Self::Item> {
149        if self.end {
150            return None;
151        }
152
153        let item = self.iter.next();
154        let _ = item.as_ref()?;
155
156        for _ in 0..self.step - 1 {
157            let next = self.iter.next();
158            if next.is_none() {
159                self.end = true;
160                break;
161            }
162        }
163
164        item
165    }
166}
167
168/// Filter object for any [`Object`].
169#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
170pub struct FilterObject<O, F, R> {
171    obj: O,
172    f: F,
173    _records: PhantomData<R>,
174}
175
176impl<O, F, R> FilterObject<O, F, R> {
177    fn new(obj: O, f: F) -> Self {
178        Self {
179            obj,
180            f,
181            _records: PhantomData,
182        }
183    }
184}
185
186impl<O, R, F> Object<R> for FilterObject<O, F, R>
187where
188    O: Object<R>,
189    F: Fn(Entity) -> bool + Clone,
190{
191    type Iter = FilterObjectIter<O::Iter, F>;
192
193    fn cells(&self, records: &R) -> Self::Iter {
194        FilterObjectIter::new(self.obj.cells(records), self.f.clone())
195    }
196}
197
198/// Filter object iterator for any [`Object`].
199#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
200pub struct FilterObjectIter<I, F> {
201    iter: I,
202    f: F,
203}
204
205impl<I, F> FilterObjectIter<I, F> {
206    fn new(iter: I, f: F) -> Self {
207        Self { iter, f }
208    }
209}
210
211impl<I, F> Iterator for FilterObjectIter<I, F>
212where
213    I: Iterator<Item = Entity>,
214    F: Fn(Entity) -> bool,
215{
216    type Item = I::Item;
217
218    fn next(&mut self) -> Option<Self::Item> {
219        loop {
220            match self.iter.next() {
221                Some(item) => {
222                    if (self.f)(item) {
223                        return Some(item);
224                    }
225                }
226                None => return None,
227            }
228        }
229    }
230}
231
232#[cfg(test)]
233mod tests {
234    use crate::{
235        grid::records::vec_records::VecRecords,
236        settings::object::{Columns, Rows},
237    };
238
239    use super::*;
240
241    #[test]
242    fn test_skip_iterator() {
243        use Entity::*;
244
245        assert_eq!(
246            cells(Rows::new(1..5).skip(1), 10, 10),
247            [Row(2), Row(3), Row(4)]
248        );
249
250        assert_eq!(
251            cells(Columns::new(5..).skip(1), 10, 10),
252            [Column(6), Column(7), Column(8), Column(9)]
253        );
254
255        assert_eq!(cells((1, 5).skip(1), 10, 10), []);
256        assert_eq!(cells((1, 5).skip(0), 10, 10), [Cell(1, 5)]);
257
258        assert_eq!(
259            cells(Rows::new(1..5).skip(0), 10, 10),
260            [Row(1), Row(2), Row(3), Row(4)]
261        );
262    }
263
264    #[test]
265    fn test_step_by_iterator() {
266        use Entity::*;
267
268        assert_eq!(cells(Rows::new(1..5).step_by(0), 10, 10), []);
269        assert_eq!(
270            cells(Rows::new(1..5).step_by(1), 10, 10),
271            [Row(1), Row(2), Row(3), Row(4)]
272        );
273        assert_eq!(cells(Rows::new(1..5).step_by(2), 10, 10), [Row(1), Row(3)]);
274
275        assert_eq!(
276            cells(Columns::new(5..).step_by(1), 10, 10),
277            [Column(5), Column(6), Column(7), Column(8), Column(9)]
278        );
279
280        assert_eq!(cells((1, 5).step_by(2), 10, 10), [Cell(1, 5)]);
281        assert_eq!(cells((1, 5).step_by(1), 10, 10), [Cell(1, 5)]);
282
283        assert_eq!(cells(Rows::new(1..5).step_by(100), 10, 10), [Row(1)]);
284    }
285
286    #[test]
287    fn test_filter_iterator() {
288        use Entity::*;
289
290        assert_eq!(
291            cells(Rows::new(1..5).filter(|i| matches!(i, Row(3))), 10, 10),
292            [Row(3)]
293        );
294        assert_eq!(cells(Rows::new(1..5).filter(|_| false), 10, 10), []);
295        assert_eq!(
296            cells(Rows::new(1..5).filter(|_| true), 10, 10),
297            [Row(1), Row(2), Row(3), Row(4)]
298        );
299    }
300
301    fn cells<O>(o: O, count_rows: usize, count_cols: usize) -> Vec<Entity>
302    where
303        O: Object<VecRecords<String>>,
304    {
305        let data = vec![vec![String::default(); count_cols]; count_rows];
306        let records = VecRecords::new(data);
307        o.cells(&records).collect::<Vec<_>>()
308    }
309}