combin_iterator/altern/vec_altern.rs
1//! # VecAltern
2//!
3//! The `vec_altern` module provides an iterator, `VecAltern`, for alternately traversing multiple iterators.
4//!
5//! ## Usage
6//!
7//! To use `VecAltern`, create a new instance with `VecAltern::new()` and add iterators using the `add` method (or `add_and` for a build pattern).
8//! You can also use the macro `altern` for more concise syntax and little performance optimization.
9//! The `next` method will then yield elements from the added iterators in a round-robin fashion until all iterators are exhausted.
10//!
11//! ## Examples
12//!
13//! ```rust
14//! use combin_iterator::altern::VecAltern;
15//! let vec1 = vec![1, 4, 7, 9];
16//! let vec2 = vec![2, 5];
17//! let vec3 = vec![3, 6, 8];
18//!
19//! // // Create a VecAltern iterator and add individual iterators, with a build pattern.
20//! let mut iter = VecAltern::new();
21//! iter.add(vec1.iter());
22//! iter.add(vec2.iter());
23//! iter.add(vec3.iter());
24//!
25//! assert_eq!(iter.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
26//!
27//! // You can also use a build pattern:
28//! let iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
29//! assert_eq!(iter.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
30//!
31//! // Alternatively, use the `altern!` macro for a more concise syntax, and some perfomance optimization
32//! use combin_iterator::altern;
33//! let iter_macro = altern!(vec1.iter(), vec2.iter(), vec3.iter());
34//!
35//! // Both iterators should yield the same results
36//! assert_eq!(iter_macro.collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6, &7, &8, &9]);
37//! ```
38//!
39//! ## Notes
40//!
41//! - The `altern!` macro provides a convenient way to create an `Altern` iterator with a cleaner syntax, and
42//! a little performance optimization (with the function: `with_capacity`, like in `Vec`). If you know at
43//! compile time how many iter you will altern between, then use the `altern!` macro.
44
45
46/// Struct to altern between several iterator
47pub struct VecAltern<'a, A> {
48 iters: Vec<Box<dyn Iterator<Item = A> + 'a>>,
49 current: usize,
50}
51
52impl<'a, A> VecAltern<'a, A> {
53 /// Creates a new instance of an `Altern` iterator.
54 pub fn new() -> Self {
55 Self {
56 iters: vec![],
57 current: 0,
58 }
59 }
60
61 /// Prepare the capacity, like `vec::with_capacity` does.
62 pub fn with_capacity(capacity : usize) -> Self {
63 Self {
64 iters: Vec::with_capacity(capacity),
65 current: 0
66 }
67 }
68
69 /// Adds an iterator to the `Altern` instance.
70 ///
71 /// # Arguments
72 ///
73 /// * `iterator` - An iterator of references to elements of type `A`.
74 ///
75 /// # Returns
76 ///
77 /// The updated `Altern` instance with the added iterator, to use like a builder.
78 pub fn add_and(mut self, iterator: impl Iterator<Item = A> + 'a) -> Self {
79 self.iters.push(Box::new(iterator));
80 self
81 }
82
83 /// Adds an iterator to the `Altern` instance.
84 ///
85 /// # Arguments
86 ///
87 /// * `iterator` - An iterator of references to elements of type `A`.
88 ///
89 /// # Returns
90 pub fn add(&mut self, iterator: impl Iterator<Item = A> + 'a){
91 self.iters.push(Box::new(iterator));
92 }
93}
94
95impl<'a, A> Iterator for VecAltern<'a, A>
96{
97 type Item = A;
98
99
100 /// Returns the next element in the iteration sequence.
101 ///
102 /// The `next` method alternates between the added iterators in a round-robin fashion.
103 fn next(&mut self) -> Option<A> {
104 loop {
105 if self.iters.is_empty() {
106 return None;
107 } else {
108 let next;
109 match self.iters.get_mut(self.current) {
110 Some(iter) => {
111 next = (*iter).next()
112 },
113 None => {
114 panic!("altern.current out of bound for altern.iters ")
115 },
116 }
117
118 match next {
119 Some(value) => {
120 self.current = (self.current + 1) % self.iters.len();
121 return Some(value)
122 },
123 None => {
124 let _ = self.iters.remove(self.current);
125 let n = self.iters.len().max(1);
126 self.current = self.current % n;
127 }
128 }
129 }
130 }
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::VecAltern;
137
138 #[test]
139 fn vec_altern() {
140 let vec1 = vec![1, 4, 7, 9];
141 let vec2 = vec![2, 5];
142 let vec3 = vec![3, 6, 8];
143
144 let iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
145
146 assert_eq!(iter.collect::<Vec<_>>(), vec![&1,&2,&3,&4,&5,&6,&7,&8, &9]);
147 }
148
149 #[test]
150 fn empty_vec_altern() {
151 let vec1 : Vec<u8> = vec![];
152 let vec2: Vec<u8> = vec![];
153 let vec3: Vec<u8> = vec![];
154
155 let mut iter = VecAltern::new().add_and(vec1.iter()).add_and(vec2.iter()).add_and(vec3.iter());
156
157 assert_eq!(iter.next(), None);
158 }
159
160 use crate::altern;
161 #[test]
162 fn macro_altern() {
163 let vec1 = vec![1, 4, 7, 9];
164 let vec2 = vec![2, 5];
165 let vec3 = vec![3, 6, 8];
166 let iter = altern!(vec1.iter(), vec2.iter(), vec3.iter());
167 assert_eq!(iter.collect::<Vec<_>>(), vec![&1,&2,&3,&4,&5,&6,&7,&8, &9]);
168 }
169}