rangex/
indexed_range.rs

1use crate::basic_range::*;
2
3//use std::ops::{Add, Sub, AddAssign};
4
5// Struct to represent the indexed range
6pub struct IndexedRange<T>
7where
8    T: IteratorOps,
9{
10    basic_range: BasicRange<T>,
11}
12
13impl<T> IndexedRange<T>
14where
15    T: IteratorOps,
16{
17    pub fn new(start: T, end: T, step: T::Step, inclusive: bool) -> Self {
18        // if step == T::zero() {
19        //     panic!("Step cannot be zero");
20        // }
21        IndexedRange {
22            basic_range: BasicRange::<T>::new(start, end, step, inclusive),
23        }
24    }
25}
26
27pub struct IndexedRangeIter<T>
28where
29    T: IteratorOps,
30{
31    basic_range_iter: BasicRangeIter<T>,
32    index: usize,
33}
34
35// Implement the Iterator trait for IndexedRangeIter
36impl<T> Iterator for IndexedRangeIter<T>
37where
38    T: IteratorOps,
39{
40    type Item = (usize, T);
41
42    fn next(&mut self) -> Option<Self::Item> {
43        match self.basic_range_iter.next() {
44            Some(t) => {
45                let result = (self.index, t);
46                self.index += 1;
47                Some(result)
48            }
49            None => None,
50        }
51    }
52}
53
54// Implement IntoIterator for IndexedRange
55impl<T> IntoIterator for IndexedRange<T>
56where
57    T: IteratorOps,
58{
59    type Item = (usize, T);
60    type IntoIter = IndexedRangeIter<T>;
61
62    fn into_iter(self) -> Self::IntoIter {
63        IndexedRangeIter {
64            basic_range_iter: BasicRangeIter::<T> {
65                current: self.basic_range.start,
66                end: self.basic_range.end,
67                step: self.basic_range.step,
68
69                inclusive_or_not_on_step: self.basic_range.inclusive_or_not_on_step,
70                invalid_range: self.basic_range.invalid_range,
71            },
72            index: 0,
73        }
74    }
75}
76
77#[macro_export]
78macro_rules! indexed_range_exclusive {
79    ($typename:ty, $start:expr, $end:expr) => {
80        indexed_range_exclusive!($typename, $start, $end, 1)
81    };
82    ($typename:ty, $start:expr, $end:expr, $step:expr) => {
83        IndexedRange::<$typename>::new($start, $end, $step, false)
84    };
85}
86
87#[macro_export]
88macro_rules! indexed_range_inclusive {
89    ($typename:ty, $start:expr, $end:expr) => {
90        indexed_range_inclusive!($typename, $start, $end, 1)
91    };
92    ($typename:ty, $start:expr, $end:expr, $step:expr) => {
93        IndexedRange::<$typename>::new($start, $end, $step, true)
94    };
95}
96
97#[cfg(test)]
98fn verify_indexed_range<T>(expect: &Vec<T>, r: IndexedRange<T>)
99where
100    T: IteratorOps + PartialEq + std::fmt::Debug,
101    IndexedRange<T>: IntoIterator<Item = (usize, T)>, // Ensures IndexedRange<T> can be converted into an iterator
102{
103    let mut index = 0;
104    for (i, v) in r {
105        assert_eq!(i, index, "index not correct");
106        assert!(
107            i < expect.len(),
108            "index out of bounds: len is {} but index is {}",
109            expect.len(),
110            i
111        );
112        assert_eq!(v, expect[index], "Value mismatch at index {}", index);
113        index += 1;
114    }
115    assert_eq!(index, expect.len(), "Final length mismatch");
116}
117
118#[cfg(test)]
119mod main_test {
120    use super::*;
121
122    #[test]
123    fn basic_1() {
124        let expect = vec![0, 1, 2];
125        verify_indexed_range(&expect, IndexedRange::new(0, 3, 1, false));
126        verify_indexed_range::<i32>(&expect, IndexedRange::<i32>::new(0, 3, 1, false));
127
128        let expect = vec![0, 1, 2];
129        verify_indexed_range(&expect, IndexedRange::new(0, 2, 1, true));
130    }
131
132    #[test]
133    fn basic_2() {
134        let expect = vec![0, 1, 2];
135        verify_indexed_range(&expect, indexed_range_exclusive!(i32, 0, 3));
136
137        let expect = vec![0, 1, 2];
138        verify_indexed_range(&expect, indexed_range_inclusive!(i32, 0, 2));
139
140        let expect = vec![3, 2, 1];
141        verify_indexed_range(&expect, IndexedRange::new(3, 0, -1, false));
142
143        let expect = vec![3, 2, 1];
144        verify_indexed_range(&expect, indexed_range_exclusive!(i32, 3, 0, -1));
145
146        let expect = vec![3, 2, 1];
147        verify_indexed_range(&expect, indexed_range_inclusive!(i32, 3, 1, -1));
148    }
149
150    #[test]
151    fn basic() {
152        let expect = vec![0, 2];
153        verify_indexed_range(&expect, IndexedRange::new(0, 4, 2, false));
154
155        let expect = vec![0, 2];
156        verify_indexed_range(&expect, indexed_range_exclusive!(i32, 0, 4, 2));
157
158        let expect = vec![0, 2];
159        verify_indexed_range(&expect, IndexedRange::new(0, 3, 2, false));
160
161        let expect = vec![0, 2];
162        verify_indexed_range(&expect, indexed_range_inclusive!(i32, 0, 2, 2));
163
164        let expect = vec![0, 2];
165        verify_indexed_range(&expect, indexed_range_inclusive!(i32, 0, 3, 2));
166    }
167
168    #[test]
169    //fn void_range_prop(inclusive in 0..=1) {
170    fn void_range_prop() {
171        for inclusive in 0..=1 {
172            let expect_none = vec![];
173            let expect_once = vec![0];
174            verify_indexed_range(if inclusive > 0 { &expect_once } else { &expect_none }, IndexedRange::new(0, 0, -2, inclusive > 0));
175
176            let expect_none = vec![];
177            let expect_once = vec![0];
178            verify_indexed_range(if inclusive > 0 { &expect_once } else { &expect_none }, IndexedRange::new(0, 0, 2, inclusive > 0));
179
180            let expect = vec![];
181            verify_indexed_range(&expect, IndexedRange::new(3, 0, 1, inclusive > 0));
182
183            let expect = vec![];
184            verify_indexed_range(&expect, IndexedRange::new(0, 1, -1, inclusive > 0));
185        }
186    }
187
188    #[test]
189    //fn not_on_step_1_prop(inclusive in 0..=1) {
190    fn not_on_step_1() {
191        for inclusive in 0..=1 {
192            let expect = vec![0, 2, 4];
193            verify_indexed_range(&expect, IndexedRange::new(0, 5, 2, inclusive > 0));
194        }
195    }
196
197    #[test]
198    fn not_on_step_2() {
199        for inclusive in 0..=1 {
200            let expect = vec![0, 2, 4];
201            verify_indexed_range(
202                &expect,
203                if 0 == inclusive {
204                    indexed_range_exclusive!(i32, 0, 5, 2)
205                } else {
206                    indexed_range_inclusive!(i32, 0, 5, 2)
207                },
208            );
209        }
210    }
211
212    #[test]
213    fn not_on_step_3() {
214        for inclusive in 0..=1 {
215            let expect = vec![5, 3];
216            verify_indexed_range(&expect, IndexedRange::new(5, 2, -2, inclusive > 0));
217        }
218    }
219
220    #[test]
221    fn not_on_step_4() {
222        for inclusive in 0..=1 {
223            let expect = vec![5, 3];
224            verify_indexed_range(
225                &expect,
226                if inclusive > 0 {
227                    indexed_range_inclusive!(i32, 5, 2, -2)
228                } else {
229                    indexed_range_exclusive!(i32, 5, 2, -2)
230                },
231            );
232        }
233    }
234
235    #[test]
236    #[should_panic]
237    fn zero_step() {
238        // Infinity or panic
239        for (i, value) in IndexedRange::new(0, 1, 0, false) {
240            println!("index:{} value:{}", i, value);
241        }
242
243        // Infinity or panic
244        for (i, value) in IndexedRange::new(0, 1, 0, true) {
245            println!("index:{} value:{}", i, value);
246        }
247    }
248}