lit_vek/iter.rs
1/** Iterator type returned by `cycle_n()` */
2#[derive(Clone, Debug)]
3pub struct CycleN<I> {
4 // Both `orig` and `iter` are in Option so that we don't have to
5 // call into_iter() or clone() more than necessary.
6 orig: Option<I>,
7 iter: Option<I>,
8 n: usize,
9}
10
11/** Iterator adaptor that repeats a sequence n times.
12
13 use lit_vek::cycle_n;
14
15 assert!(cycle_n([1, 2, 3], 2).eq([1, 2, 3, 1, 2, 3]));
16
17The sequence must be `IntoIter`, and the iterator must be `Clone`.
18
19This is mostly to enable the `vek![...elems, n]` syntax.
20*/
21pub fn cycle_n<I: IntoIterator>(it: I, n: usize) -> CycleN<I::IntoIter>
22where
23 I::IntoIter: Clone,
24{
25 match n {
26 0 => CycleN {
27 orig: None,
28 iter: None,
29 n,
30 },
31 1 => {
32 let it = it.into_iter();
33 CycleN {
34 orig: None,
35 iter: Some(it),
36 n,
37 }
38 }
39 _ => {
40 let i1 = it.into_iter();
41 let i2 = i1.clone();
42 CycleN {
43 orig: Some(i1),
44 iter: Some(i2),
45 n,
46 }
47 }
48 }
49}
50
51impl<I: Iterator + Clone> Iterator for CycleN<I> {
52 type Item = I::Item;
53
54 fn next(&mut self) -> Option<Self::Item> {
55 while let Some(it) = &mut self.iter {
56 if let Some(x) = it.next() {
57 return Some(x);
58 }
59 self.n -= 1;
60 if self.n < 2 {
61 self.iter = self.orig.take();
62 } else {
63 self.iter = self.orig.clone();
64 }
65 }
66 None
67 }
68}
69
70/**
71Chain one more elements or iterables together into one sequence, using "spread"
72syntax.
73
74 # use {lit_vek::iter, std::array};
75
76 let arr = [1, 2, 3];
77 let vec = vec![8, 9, 10];
78
79 assert!(
80 iter![...arr, 4, ...(5..7), 7, ...vec]
81 .eq([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]));
82
83`iter![a, b, c]` simply returns an iterator over those elements, exactly like
84`[a, b, c].into_iter()`. But elements can be prefixed with `...` to indicate
85a "spread": they are chained into the resulting iterator with
86`std::iter::chain()`.
87
88See `[lit_vek::vek]` in this crate for more explanation of the syntax.
89
90# Examples
91
92 use {lit_vek::{iter, CycleN}, std::{array, iter}};
93 let ints = [1, 2, 3];
94
95 // Empty invocations of iter! expand to [std::iter::empty].
96 let _: iter::Empty<i32> = iter![];
97
98 // One or more arguments expand to Array::IntoIter.
99 let _: array::IntoIter<_, 1> = iter![1];
100 let _: array::IntoIter<_, 3> = iter![1, 2, 3];
101
102 // The `[x; n]` syntax expands to [std::iter::repeat(x).take(n)]
103 let _: iter::Take<iter::Repeat<_>> = iter![0; 5];
104
105 // The `[...x; n]` syntax expands to [`cycle_n`] from this crate
106 let _: CycleN<_> = iter![...ints; 3];
107
108 // And chaining expands to [std::iter::Chain]
109 let _: iter::Chain<_, _> = iter![...ints, ...ints];
110
111# See also
112
113The `vek![]` macro in this crate is a drop-in replacement for `vec![]`,
114but enables the same spread syntax. It is equivalent to
115`iter![].collect::<Vec<_>>()`.
116
117The `itertools::chain!` macro is similar, except it takes only iterable
118arguments rather than a mix of iterables and single elements.
119
120```ignore
121 chain![a, b, iter::once(c)] == iter![...a, ...b, c]
122```
123*/
124#[macro_export]
125macro_rules! iter {
126 // empty
127 () => { ::std::iter::empty() };
128
129 // [x; n]
130 ($x:tt; $n:expr) => {
131 ::std::iter::repeat($x).take($n)
132 };
133
134 // [...x; n]
135 (...$x:tt; $n:expr) => {
136 $crate::cycle_n($x, $n)
137 };
138
139 // [...[x; n] at start
140 (...[...$xs:expr; $n:expr] $($tail:tt)*) => {
141 $crate::iter![...$crate::cycle_n($xs, $n) $($tail)*]
142 };
143
144 // simple array at start
145 (...$some:tt $(,)? ) => {
146 ::std::iter::IntoIterator::into_iter($some)
147 };
148
149 // ...[...x; n] in second item; convert to repeat_n
150 (...$some:tt, ...[...$x:tt; $n:expr] $($tail:tt)*) => {
151 $crate::iter![...$some, ...$crate::cycle_n($x, $n) $($tail)*]
152 };
153
154 // ...[x; n] in second item; convert to simple expr
155 (...$some:tt, ...[$x:tt; $n:expr] $($tail:tt)*) => {
156 $crate::iter![...$some, ...std::iter::repeat($x).take($n) $($tail)*]
157 };
158
159 // ...xs in second item and nothing else; final chain()
160 (...$some:tt, ...$xs:expr $(,)?) => {
161 ::std::iter::Iterator::chain(
162 ::std::iter::IntoIterator::into_iter($some),
163 $xs)
164 };
165
166 // ...xs in second item followed by more; continue chain()
167 (...$some:tt, ...$xs:expr, $($tail:tt)*) => {
168 $crate::iter![
169 ... ::std::iter::Iterator::chain(
170 ::std::iter::IntoIterator::into_iter($some),
171 $xs),
172 $($tail)*
173 ]
174 };
175
176 // shift a single elem into the starting literal
177 (...[$($some:tt)*], $x:tt $(, $($tail:tt)*)?) => {
178 $crate::iter![...[$($some)*, $x], $($($tail)*)?]
179 };
180
181 // first element is a (non-literal) spread
182 (...$xs:expr $(, $($tail:tt)*)?) => {
183 ::std::iter::Iterator::chain(
184 ::std::iter::IntoIterator::into_iter($xs),
185 $crate::iter![ $($($tail)*)? ])
186 };
187
188 // shift a single elem into a new starting literal
189 ($x:expr $(, $($tail:tt)*)?) => {
190 $crate::iter![...[$x], $($($tail)*)? ]
191 };
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197
198 #[test]
199 fn test_cycle_n() {
200 assert!(cycle_n(1..4, 0).eq([]));
201 assert!(cycle_n(1..4, 1).eq([1, 2, 3]));
202 assert!(cycle_n(1..4, 2).eq([1, 2, 3, 1, 2, 3]));
203
204 assert!(cycle_n(0..0, 10).eq([]));
205 }
206
207 #[test]
208 fn test_iter() {
209 assert_eq!(Vec::<u32>::new(), iter![].collect::<Vec<_>>());
210
211 assert_eq!(vec![1], iter![1].collect::<Vec<_>>());
212 assert_eq!(vec![1, 2], iter![1, 2].collect::<Vec<_>>());
213 assert_eq!(vec![1, 2, 3], iter![1, 2, 3].collect::<Vec<_>>());
214
215 assert_eq!(vec![1], iter![...[1]].collect::<Vec<_>>());
216 assert_eq!(vec![1, 2], iter![...[1,2]].collect::<Vec<_>>());
217
218 assert_eq!(vec![1, 2], iter![1,...[2]].collect::<Vec<_>>());
219 assert_eq!(vec![1, 2, 3], iter![...[1], ...[2,3]].collect::<Vec<_>>());
220 assert_eq!(
221 vec![1, 2, 3, 4, 5, 6],
222 iter![1, ...[2,3], 4, ...[], 5, ...[6]].collect::<Vec<_>>()
223 );
224 }
225}