1use core::iter::Iterator;
3
4#[derive(Clone, Debug)]
5#[must_use = "iterators are lazy and do nothing unless consumed"]
6pub struct CycleToNth<I> {
7 orig: I,
8 iter: I,
9 nth: usize,
10 n: usize,
11}
12
13impl<I: Clone> CycleToNth<I> {
14 pub fn new(iter: I, nth: usize) -> CycleToNth<I> {
15 CycleToNth {
16 orig: iter.clone(),
17 iter,
18 nth,
19 n: 0,
20 }
21 }
22}
23
24impl<I> Iterator for CycleToNth<I>
25where
26 I: Clone + Iterator,
27{
28 type Item = <I as Iterator>::Item;
29
30 #[inline]
31 fn next(&mut self) -> Option<<I as Iterator>::Item> {
32 if self.n == self.nth {
33 None
35 } else {
36 self.n += 1;
37 match self.iter.next() {
38 None => {
39 self.iter = self.orig.clone();
40 self.iter.next()
41 }
42 y => y,
43 }
44 }
45 }
46
47 #[inline]
48 fn size_hint(&self) -> (usize, Option<usize>) {
49 match self.orig.size_hint() {
51 sz @ (0, Some(0)) => sz,
52 (0, _) => (0, None),
53 _ => (usize::MAX, None),
54 }
55 }
56}
57
58pub trait CycleToNthAdapter
59where
60 Self: Sized + Clone,
61{
62 fn cycle_to_nth(self, nth: usize) -> CycleToNth<Self>;
63}
64
65impl<I> CycleToNthAdapter for I
66where
67 Self: Sized + Clone,
68 I: Iterator,
69{
70 fn cycle_to_nth(self, nth: usize) -> CycleToNth<Self> {
71 CycleToNth::new(self, nth)
72 }
73}
74
75#[cfg(test)]
76mod test {
77 use crate::*;
78
79 #[test]
80 fn extend_with_cycles() {
81 let v = vec![1u32];
82 assert_eq!(v.iter().cycle_to_nth(5).sum::<u32>(), 5u32);
83 }
84
85 #[test]
86 fn truncate_to_nth() {
87 let v = vec![1u32; 10];
88 assert_eq!(v.iter().cycle_to_nth(5).sum::<u32>(), 5u32);
89 }
90}