1#![no_std]
2#![doc = include_str!("../README.md")]
3#![warn(clippy::pedantic)]
4
5use core::{fmt::Debug, iter::FusedIterator};
6
7use alloc::vec::{IntoIter, Vec};
8
9extern crate alloc;
10
11#[must_use]
13#[derive(Debug, Clone)]
14pub struct ForwardIter<I: Iterator> {
15 iter: Option<I>,
16 buf: IntoIter<I::Item>,
17}
18
19impl<I: Iterator> ForwardIter<I> {
20 fn backward(&mut self) -> &mut IntoIter<I::Item> {
21 if let Some(iter) = self.iter.take() {
22 self.buf = iter.collect::<Vec<_>>().into_iter();
23 }
24 &mut self.buf
25 }
26}
27
28macro_rules! choice {
29 ($self:ident:$name:ident $t:tt) => {
30 $self.iter.as_mut()
31 .map_or_else(|| $self.buf.$name $t, |iter| iter.$name $t)
32 };
33}
34
35impl<I: Iterator + FusedIterator> FusedIterator for ForwardIter<I> {}
36impl<I: Iterator + ExactSizeIterator> ExactSizeIterator for ForwardIter<I> {}
37impl<I: Iterator> Iterator for ForwardIter<I> {
38 type Item = I::Item;
39
40 fn next(&mut self) -> Option<Self::Item> {
41 choice!(self:next())
42 }
43
44 fn nth(&mut self, n: usize) -> Option<Self::Item> {
45 choice!(self:nth(n))
46 }
47
48 fn size_hint(&self) -> (usize, Option<usize>) {
49 self.iter.as_ref()
50 .map_or_else(|| self.buf.size_hint(), I::size_hint)
51 }
52
53 fn fold<B, F>(self, init: B, f: F) -> B
54 where Self: Sized,
55 F: FnMut(B, Self::Item) -> B,
56 {
57 match self.iter {
58 Some(iter) => iter.fold(init, f),
59 None => self.buf.fold(init, f),
60 }
61 }
62}
63impl<I: Iterator> DoubleEndedIterator for ForwardIter<I> {
64 fn next_back(&mut self) -> Option<Self::Item> {
65 self.backward().next_back()
66 }
67
68 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
69 self.backward().nth_back(n)
70 }
71
72 fn rfold<B, F>(mut self, init: B, f: F) -> B
73 where Self: Sized,
74 F: FnMut(B, Self::Item) -> B,
75 {
76 self.backward();
77 self.buf.rfold(init, f)
78 }
79}
80
81pub trait ForwardIterExt: Iterator + Sized {
83 fn forward(self) -> ForwardIter<Self> {
107 ForwardIter {
108 iter: Some(self),
109 buf: IntoIter::default(),
110 }
111 }
112}
113impl<I: Iterator> ForwardIterExt for I { }
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn some_next() {
121 let mut i = 0;
122 let iter = &mut (0..4).map(|_| { i += 1; i }).forward();
123 assert_eq!(iter.next(), Some(1));
124 let x: Vec<_> = iter.rev().collect();
125 assert_eq!(x, [4, 3, 2]);
126 }
127
128 #[test]
129 fn some_next2() {
130 let mut i = 0;
131 let iter = &mut (0..4).map(|_| { i += 1; i }).forward();
132 assert_eq!(iter.next(), Some(1));
133 assert_eq!(iter.next_back(), Some(4));
134 assert_eq!(iter.next(), Some(2));
135 assert_eq!(iter.next_back(), Some(3));
136 assert_eq!(iter.next(), None);
137 assert_eq!(iter.next_back(), None);
138 }
139}