1use crate::basic_range::*;
2
3pub 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 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
35impl<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
54impl<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)>, {
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() {
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() {
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 for (i, value) in IndexedRange::new(0, 1, 0, false) {
240 println!("index:{} value:{}", i, value);
241 }
242
243 for (i, value) in IndexedRange::new(0, 1, 0, true) {
245 println!("index:{} value:{}", i, value);
246 }
247 }
248}