core_extensions/
iterators.rs

1//! Iterator adaptors and constructors.
2
3use std_::{
4    cmp::Ordering,
5    iter::{Product, Sum},
6    mem,
7};
8
9
10/// A version of [`std::iter::OnceWith`] usable in Rust 1.41.0.
11///
12/// # Example
13///
14/// ```
15/// use core_extensions::iterators::LazyOnce;
16///
17/// let mut number = 0;
18///
19/// // The closure here is never ran.
20/// LazyOnce::new(||{ number+=10; number });
21///
22/// assert_eq!(number, 0);
23///
24/// for i in LazyOnce::new(||{ number+=10; number }) {
25///     assert_eq!(i, 10);
26/// }
27///
28/// assert_eq!(number, 10);
29///
30/// ```
31///
32/// [`std::iter::OnceWith`]: https://doc.rust-lang.org/std/iter/struct.OnceWith.html
33/// [`Iterator::next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
34///
35#[derive(Debug, Copy, Clone)]
36pub struct LazyOnce<F> {
37    func: Option<F>,
38}
39
40impl<F> LazyOnce<F> {
41    /// Constructs a LazyOnce.
42    pub fn new(f: F) -> Self {
43        LazyOnce { func: Some(f) }
44    }
45}
46
47impl<F, T> Iterator for LazyOnce<F>
48where
49    F: FnOnce() -> T,
50{
51    type Item = T;
52
53    fn next(&mut self) -> Option<T> {
54        self.func.take().map(|f| f())
55    }
56
57    fn size_hint(&self) -> (usize, Option<usize>) {
58        (1, Some(1))
59    }
60}
61
62impl<F, T> DoubleEndedIterator for LazyOnce<F>
63where
64    F: FnOnce() -> T,
65{
66    fn next_back(&mut self) -> Option<T> {
67        self.func.take().map(|f| f())
68    }
69}
70
71impl<F, T> ExactSizeIterator for LazyOnce<F> where F: FnOnce() -> T {}
72
73////////////////////////////////////////////////////////////////////////////////
74
75#[derive(Debug, Clone)]
76struct Unreplaced<T> {
77    nth: usize,
78    current: usize,
79    with: T,
80}
81
82#[derive(Debug, Clone)]
83enum ReplaceNthState<T> {
84    Unreplaced(Unreplaced<T>),
85    Replaced,
86}
87
88/// An Iterator that replaces the `nth` element with another value.
89///
90/// # Example
91///
92/// ```rust
93/// use core_extensions::iterators::ReplaceNth;
94///
95/// // This iterator replaces the 4th element with `100`
96/// let list = ReplaceNth::new(0..=6, 4, 100).collect::<Vec<_>>();
97///
98/// assert_eq!(list, vec![0, 1, 2, 3, 100, 5, 6]);
99///
100/// ```
101///
102#[derive(Debug, Clone)]
103pub struct ReplaceNth<I>
104where
105    I: Iterator,
106{
107    iter: I,
108    state: ReplaceNthState<I::Item>,
109}
110
111impl<I> ReplaceNth<I>
112where
113    I: Iterator,
114{
115    /// Constructs a `ReplaceNth`.
116    pub fn new(iter: I, nth: usize, with: I::Item) -> Self {
117        Self {
118            iter,
119            state: ReplaceNthState::Unreplaced(Unreplaced {
120                nth,
121                current: 0,
122                with,
123            }),
124        }
125    }
126}
127
128impl<I> Iterator for ReplaceNth<I>
129where
130    I: Iterator,
131{
132    type Item = I::Item;
133
134    fn next(&mut self) -> Option<I::Item> {
135        use self::ReplaceNthState as RNS;
136
137        let mut ret = self.iter.next()?;
138
139        let replace = match self.state {
140            RNS::Unreplaced(ref mut unreplaced) => {
141                let x = unreplaced.nth == unreplaced.current;
142                if !x {
143                    unreplaced.current += 1
144                }
145                x
146            }
147            RNS::Replaced => false,
148        };
149        if replace {
150            if let RNS::Unreplaced(unreplaced) = mem::replace(&mut self.state, RNS::Replaced) {
151                ret = unreplaced.with;
152            }
153        }
154        Some(ret)
155    }
156
157    fn nth(&mut self, nth: usize) -> Option<I::Item> {
158        use self::ReplaceNthState as RNS;
159
160        let mut ret = self.iter.nth(nth)?;
161
162        let mut replace = Ordering::Greater;
163        if let RNS::Unreplaced(ref mut unreplaced) = self.state {
164            unreplaced.current += nth;
165            replace = unreplaced.current.cmp(&unreplaced.nth);
166            if replace == Ordering::Less {
167                unreplaced.current += 1;
168            }
169        }
170        match replace {
171            Ordering::Less => {}
172            Ordering::Equal => {
173                if let RNS::Unreplaced(unreplaced) = mem::replace(&mut self.state, RNS::Replaced) {
174                    ret = unreplaced.with;
175                }
176            }
177            Ordering::Greater => self.state = RNS::Replaced,
178        }
179        Some(ret)
180    }
181
182    fn size_hint(&self) -> (usize, Option<usize>) {
183        self.iter.size_hint()
184    }
185
186    fn count(self) -> usize {
187        self.iter.count()
188    }
189}
190
191#[cfg(test)]
192#[cfg(feature = "alloc")]
193mod test_replace_nth {
194    use alloc::vec::Vec;
195
196    use super::*;
197    #[test]
198    fn nth_method() {
199        let list = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
200
201        for i in 0..list.len() {
202            let mut iter = ReplaceNth::new(list.iter().cloned(), i, 100);
203            if i != 0 {
204                let j = i - 1;
205                assert_eq!(iter.nth(j).unwrap(), list[j])
206            }
207            assert_eq!(iter.next().unwrap(), 100);
208            if i + 1 < list.len() {
209                assert_eq!(iter.next().unwrap(), list[i + 1]);
210            }
211            if i + 2 < list.len() {
212                assert_eq!(iter.next().unwrap(), list[i + 2]);
213            }
214        }
215    }
216}
217
218////////////////////////////////////////////////////////////////////////////////
219
220/// Extension trait for [`std::iter::Iterator`] implementors.
221///
222/// [`std::iter::Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
223pub trait IteratorExt: Iterator {
224    /// Collects into an existing collection by extending it.
225    ///
226    /// # Example
227    ///
228    /// ```
229    /// use core_extensions::iterators::IteratorExt;
230    ///
231    /// let mut list = vec![101, 102];
232    ///
233    /// (0..10)
234    ///     .filter(|&v| v<5 )
235    ///     .map(|v| v*2 )
236    ///     .extending(&mut list);
237    ///
238    /// assert_eq!(list, vec![101, 102, 0, 2, 4, 6, 8]);
239    ///
240    /// ```
241    #[inline(always)]
242    fn extending<C>(self, extend: &mut C)
243    where
244        Self: Sized,
245        C: Extend<Self::Item>,
246    {
247        extend.extend(self);
248    }
249
250    /// Collects into a pre-allocated collection,returning it by value.
251    ///
252    /// # Example
253    ///
254    /// ```
255    /// use core_extensions::iterators::IteratorExt;
256    ///
257    /// let list = (0..10)
258    ///     .filter(|&v| v<5 )
259    ///     .map(|v| v*2 )
260    ///     .collect_into(Vec::with_capacity(5));
261    ///
262    /// assert_eq!(list.capacity(), 5);
263    /// assert_eq!(list, vec![0, 2, 4, 6, 8]);
264    ///
265    /// ```
266    /// # Example
267    ///
268    /// Reusing an existing collection.
269    ///
270    /// ```
271    /// use core_extensions::iterators::IteratorExt;
272    ///
273    /// let mut list = Vec::with_capacity(7);
274    /// list.push(100);
275    /// list.push(101);
276    ///
277    /// let list = (0..10)
278    ///     .filter(|&v| v<5 )
279    ///     .map(|v| v*2 )
280    ///     .collect_into(list);
281    ///
282    /// assert_eq!(list.capacity(),7);
283    /// assert_eq!(list, vec![100, 101, 0, 2, 4, 6, 8]);
284    ///
285    /// ```
286    #[inline(always)]
287    fn collect_into<C>(self, mut extend: C) -> C
288    where
289        Self: Sized,
290        C: Extend<Self::Item>,
291    {
292        extend.extend(self);
293        extend
294    }
295
296    /// An Iterator that replaces the nth element with another value.
297    ///
298    /// # Example
299    /// ```
300    /// use core_extensions::iterators::IteratorExt;
301    ///
302    /// assert_eq!(
303    ///     (0..=9).replace_nth(5, 1337).collect::<Vec<_>>(),
304    ///     vec![0, 1, 2, 3, 4, 1337, 6, 7, 8, 9]
305    /// );
306    ///
307    /// let list = vec!["hello", "dear", "world"];
308    ///
309    /// assert_eq!(
310    ///     list.into_iter().replace_nth(1, "my").collect::<Vec<_>>(),
311    ///     vec!["hello", "my", "world"]
312    /// );
313    ///
314    ///
315    /// ```
316    #[inline(always)]
317    fn replace_nth(self, nth: usize, with: Self::Item) -> ReplaceNth<Self>
318    where
319        Self: Sized,
320    {
321        ReplaceNth::new(self, nth, with)
322    }
323
324    /// Sums the items of the iterator, into the item's type.
325    ///
326    /// This like the [`Iterator::sum`] method, with better type inference,
327    /// since with the [`Iterator::sum`] method you must specify its return type.
328    ///
329    /// # Example
330    /// 
331    /// ```rust
332    /// use core_extensions::iterators::IteratorExt;
333    ///
334    /// assert_eq!((1..=4).sum_same(), 10);
335    /// 
336    /// let arr = [3, 7, 11, 29];
337    /// assert_eq!(arr.iter().copied().sum_same(), 50);
338    /// 
339    /// ```
340    ///  
341    /// [`Iterator::sum`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.sum 
342    #[inline]
343    fn sum_same(self) -> Self::Item
344    where
345        Self: Sized,
346        Self::Item: Sum,
347    {
348        <Self::Item as Sum<Self::Item>>::sum(self)
349    }
350
351    /// Multiplies the items of the iterator, into the item's type.
352    ///
353    /// This like the [`Iterator::product`] method, with better type inference,
354    /// since with the [`Iterator::product`] method you must specify its return type.
355    ///
356    /// # Example
357    /// 
358    /// ```rust
359    /// use core_extensions::iterators::IteratorExt;
360    ///
361    /// assert_eq!((1..=4).product_same(), 24);
362    /// 
363    /// let arr = [3, 4, 6];
364    /// assert_eq!(arr.iter().copied().product_same(), 72);
365    /// 
366    /// ```
367    ///  
368    /// [`Iterator::product`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.product
369    #[inline]
370    fn product_same(self) -> Self::Item
371    where
372        Self: Sized,
373        Self::Item: Product,
374    {
375        <Self::Item as Product<Self::Item>>::product(self)
376    }
377}
378
379impl<I> IteratorExt for I where I: ?Sized + Iterator {}
380
381////////////////////////////////////////////////////////////////////////////////
382
383/// Uses a closure to construct `Iterator`s.
384///
385/// This can turn this into an `Iterator` (with `IntoIterator::into_iter`)
386/// multiple times if the closure is `Copy`.
387///
388/// # Example
389///
390/// ```rust
391/// use core_extensions::iterators::IterConstructor;
392///
393/// let list = vec!["hello", "world"];
394///
395/// let constructor = IterConstructor(||{
396///     list.iter().enumerate().map(|(i,v)| v.repeat(i) )
397/// });
398///
399/// for _ in 0..2 {
400///     assert_eq!(
401///         constructor.into_iter().collect::<Vec<_>>(),
402///         ["".to_string(), "world".to_string()],
403///     );
404/// }
405///
406/// ```
407#[derive(Debug, Copy, Clone)]
408pub struct IterConstructor<F> (pub F);
409
410impl<F, I> IntoIterator for IterConstructor<F>
411where
412    F: FnOnce() -> I,
413    I: IntoIterator,
414{
415    type Item = I::Item;
416    type IntoIter = I::IntoIter;
417
418    #[inline]
419    fn into_iter(self) -> Self::IntoIter {
420        (self.0)().into_iter()
421    }
422}
423
424////////////////////////////////////////////////////////////////////////////////
425
426/// Use this macro to create an
427/// [`IterCloner`](./iterators/struct.IterCloner.html)
428/// from an [`IntoIterator`] (this includes all [`Iterator`]s).
429///
430/// The resulting variable clones the iterator (that `$expr` was converted into)
431/// every time that you call `.into_iter()` or iterate over it with a `for` loop.
432///
433/// # Example
434///
435/// ### Mapping
436///
437/// ```rust
438/// use core_extensions::iter_cloner;
439/// 
440/// let list = vec!["this", "is", "not", "really", "great"];
441///
442/// let lengths = vec![4, 2, 3, 6, 5];
443///
444/// iter_cloner!(let iter = list.iter().map(|v|v.len()));
445///
446/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), lengths);
447/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), lengths);
448/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), lengths);
449///
450/// ```
451///
452/// ### Vector
453///
454/// ```rust
455/// use core_extensions::iter_cloner;
456///
457/// iter_cloner!(let iter = vec![0, 1, 2, 3]);
458///
459/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
460/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
461/// assert_eq!(iter.into_iter().collect::<Vec<_>>(), [0, 1, 2, 3]);
462///
463/// ```
464///
465/// [`IntoIterator`]: https://doc.rust-lang.org/std/iter/trait.IntoIterator.html
466/// [`Iterator`]:  https://doc.rust-lang.org/std/iter/trait.Iterator.html
467#[cfg(feature = "iterators")]
468#[cfg_attr(feature = "docsrs", doc(cfg(feature = "iterators")))]
469#[macro_export]
470macro_rules! iter_cloner {
471    (let $ident:ident = $expr:expr) => {
472        let $ident = $crate::std_::iter::IntoIterator::into_iter($expr);
473        let $ident = $crate::iterators::IterCloner(&$ident);
474    };
475}
476
477/// Implements [`IntoIterator::into_iter`] by cloning the iterator it references.
478///
479/// You can also use the [`iter_cloner`](../macro.iter_cloner.html) macro to
480/// construct this,
481///
482/// # Example
483///
484/// ```
485///
486/// use core_extensions::iterators::IterCloner;
487///
488/// let list = vec!["hello", "awesome", "world"];
489///
490/// let iter = list.iter().map(|v|v.len()).filter(|&v| v<6 );
491///
492/// let iter_clone = IterCloner(&iter);
493///    
494/// for _ in 0..2{
495///     assert_eq!(iter_clone.into_iter().collect::<Vec<_>>(), vec![5, 5]);
496/// }
497///
498/// ```
499///
500/// [`IntoIterator::into_iter`]: 
501/// https://doc.rust-lang.org/std/iter/trait.IntoIterator.html#tymethod.into_iter
502///
503#[derive(Debug)]
504pub struct IterCloner<'a, I: 'a> (pub &'a I);
505
506impl<'a, I> Copy for IterCloner<'a, I> {}
507impl<'a, I> Clone for IterCloner<'a, I> {
508    fn clone(&self) -> Self {
509        *self
510    }
511}
512
513impl<'a, I: 'a> IntoIterator for IterCloner<'a, I>
514where
515    I: Iterator + Clone,
516{
517    type Item = I::Item;
518    type IntoIter = I;
519
520    fn into_iter(self) -> Self::IntoIter {
521        self.0.clone()
522    }
523}