Skip to content

Commit 773b73c

Browse files
committed
Split iterator adaptors into individual modules
This commit also makes fields of `Take` private. I have no idea why they were `pub(super)` before.
1 parent 3adedb8 commit 773b73c

21 files changed

+2969
-2833
lines changed
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use crate::{
2+
iter::{
3+
adapters::zip::try_get_unchecked, adapters::TrustedRandomAccess, FusedIterator, TrustedLen,
4+
},
5+
ops::Try,
6+
};
7+
8+
/// An iterator that clones the elements of an underlying iterator.
9+
///
10+
/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
11+
/// documentation for more.
12+
///
13+
/// [`cloned`]: Iterator::cloned
14+
/// [`Iterator`]: trait.Iterator.html
15+
#[stable(feature = "iter_cloned", since = "1.1.0")]
16+
#[must_use = "iterators are lazy and do nothing unless consumed"]
17+
#[derive(Clone, Debug)]
18+
pub struct Cloned<I> {
19+
it: I,
20+
}
21+
22+
impl<I> Cloned<I> {
23+
pub(in crate::iter) fn new(it: I) -> Cloned<I> {
24+
Cloned { it }
25+
}
26+
}
27+
28+
fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
29+
move |acc, elt| f(acc, elt.clone())
30+
}
31+
32+
#[stable(feature = "iter_cloned", since = "1.1.0")]
33+
impl<'a, I, T: 'a> Iterator for Cloned<I>
34+
where
35+
I: Iterator<Item = &'a T>,
36+
T: Clone,
37+
{
38+
type Item = T;
39+
40+
fn next(&mut self) -> Option<T> {
41+
self.it.next().cloned()
42+
}
43+
44+
fn size_hint(&self) -> (usize, Option<usize>) {
45+
self.it.size_hint()
46+
}
47+
48+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
49+
where
50+
Self: Sized,
51+
F: FnMut(B, Self::Item) -> R,
52+
R: Try<Ok = B>,
53+
{
54+
self.it.try_fold(init, clone_try_fold(f))
55+
}
56+
57+
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
58+
where
59+
F: FnMut(Acc, Self::Item) -> Acc,
60+
{
61+
self.it.map(T::clone).fold(init, f)
62+
}
63+
64+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
65+
where
66+
Self: TrustedRandomAccess,
67+
{
68+
// SAFETY: the caller must uphold the contract for
69+
// `Iterator::__iterator_get_unchecked`.
70+
unsafe { try_get_unchecked(&mut self.it, idx).clone() }
71+
}
72+
}
73+
74+
#[stable(feature = "iter_cloned", since = "1.1.0")]
75+
impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
76+
where
77+
I: DoubleEndedIterator<Item = &'a T>,
78+
T: Clone,
79+
{
80+
fn next_back(&mut self) -> Option<T> {
81+
self.it.next_back().cloned()
82+
}
83+
84+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
85+
where
86+
Self: Sized,
87+
F: FnMut(B, Self::Item) -> R,
88+
R: Try<Ok = B>,
89+
{
90+
self.it.try_rfold(init, clone_try_fold(f))
91+
}
92+
93+
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
94+
where
95+
F: FnMut(Acc, Self::Item) -> Acc,
96+
{
97+
self.it.map(T::clone).rfold(init, f)
98+
}
99+
}
100+
101+
#[stable(feature = "iter_cloned", since = "1.1.0")]
102+
impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
103+
where
104+
I: ExactSizeIterator<Item = &'a T>,
105+
T: Clone,
106+
{
107+
fn len(&self) -> usize {
108+
self.it.len()
109+
}
110+
111+
fn is_empty(&self) -> bool {
112+
self.it.is_empty()
113+
}
114+
}
115+
116+
#[stable(feature = "fused", since = "1.26.0")]
117+
impl<'a, I, T: 'a> FusedIterator for Cloned<I>
118+
where
119+
I: FusedIterator<Item = &'a T>,
120+
T: Clone,
121+
{
122+
}
123+
124+
#[doc(hidden)]
125+
#[unstable(feature = "trusted_random_access", issue = "none")]
126+
unsafe impl<I> TrustedRandomAccess for Cloned<I>
127+
where
128+
I: TrustedRandomAccess,
129+
{
130+
#[inline]
131+
fn may_have_side_effect() -> bool {
132+
true
133+
}
134+
}
135+
136+
#[unstable(feature = "trusted_len", issue = "37572")]
137+
unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
138+
where
139+
I: TrustedLen<Item = &'a T>,
140+
T: Clone,
141+
{
142+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use crate::{
2+
iter::{
3+
adapters::zip::try_get_unchecked, adapters::TrustedRandomAccess, FusedIterator, TrustedLen,
4+
},
5+
ops::Try,
6+
};
7+
8+
/// An iterator that copies the elements of an underlying iterator.
9+
///
10+
/// This `struct` is created by the [`copied`] method on [`Iterator`]. See its
11+
/// documentation for more.
12+
///
13+
/// [`copied`]: Iterator::copied
14+
/// [`Iterator`]: trait.Iterator.html
15+
#[stable(feature = "iter_copied", since = "1.36.0")]
16+
#[must_use = "iterators are lazy and do nothing unless consumed"]
17+
#[derive(Clone, Debug)]
18+
pub struct Copied<I> {
19+
it: I,
20+
}
21+
22+
impl<I> Copied<I> {
23+
pub(in crate::iter) fn new(it: I) -> Copied<I> {
24+
Copied { it }
25+
}
26+
}
27+
28+
fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
29+
move |acc, &elt| f(acc, elt)
30+
}
31+
32+
fn copy_try_fold<T: Copy, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
33+
move |acc, &elt| f(acc, elt)
34+
}
35+
36+
#[stable(feature = "iter_copied", since = "1.36.0")]
37+
impl<'a, I, T: 'a> Iterator for Copied<I>
38+
where
39+
I: Iterator<Item = &'a T>,
40+
T: Copy,
41+
{
42+
type Item = T;
43+
44+
fn next(&mut self) -> Option<T> {
45+
self.it.next().copied()
46+
}
47+
48+
fn size_hint(&self) -> (usize, Option<usize>) {
49+
self.it.size_hint()
50+
}
51+
52+
fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
53+
where
54+
Self: Sized,
55+
F: FnMut(B, Self::Item) -> R,
56+
R: Try<Ok = B>,
57+
{
58+
self.it.try_fold(init, copy_try_fold(f))
59+
}
60+
61+
fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
62+
where
63+
F: FnMut(Acc, Self::Item) -> Acc,
64+
{
65+
self.it.fold(init, copy_fold(f))
66+
}
67+
68+
fn nth(&mut self, n: usize) -> Option<T> {
69+
self.it.nth(n).copied()
70+
}
71+
72+
fn last(self) -> Option<T> {
73+
self.it.last().copied()
74+
}
75+
76+
fn count(self) -> usize {
77+
self.it.count()
78+
}
79+
80+
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
81+
where
82+
Self: TrustedRandomAccess,
83+
{
84+
// SAFETY: the caller must uphold the contract for
85+
// `Iterator::__iterator_get_unchecked`.
86+
*unsafe { try_get_unchecked(&mut self.it, idx) }
87+
}
88+
}
89+
90+
#[stable(feature = "iter_copied", since = "1.36.0")]
91+
impl<'a, I, T: 'a> DoubleEndedIterator for Copied<I>
92+
where
93+
I: DoubleEndedIterator<Item = &'a T>,
94+
T: Copy,
95+
{
96+
fn next_back(&mut self) -> Option<T> {
97+
self.it.next_back().copied()
98+
}
99+
100+
fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
101+
where
102+
Self: Sized,
103+
F: FnMut(B, Self::Item) -> R,
104+
R: Try<Ok = B>,
105+
{
106+
self.it.try_rfold(init, copy_try_fold(f))
107+
}
108+
109+
fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
110+
where
111+
F: FnMut(Acc, Self::Item) -> Acc,
112+
{
113+
self.it.rfold(init, copy_fold(f))
114+
}
115+
}
116+
117+
#[stable(feature = "iter_copied", since = "1.36.0")]
118+
impl<'a, I, T: 'a> ExactSizeIterator for Copied<I>
119+
where
120+
I: ExactSizeIterator<Item = &'a T>,
121+
T: Copy,
122+
{
123+
fn len(&self) -> usize {
124+
self.it.len()
125+
}
126+
127+
fn is_empty(&self) -> bool {
128+
self.it.is_empty()
129+
}
130+
}
131+
132+
#[stable(feature = "iter_copied", since = "1.36.0")]
133+
impl<'a, I, T: 'a> FusedIterator for Copied<I>
134+
where
135+
I: FusedIterator<Item = &'a T>,
136+
T: Copy,
137+
{
138+
}
139+
140+
#[doc(hidden)]
141+
#[unstable(feature = "trusted_random_access", issue = "none")]
142+
unsafe impl<I> TrustedRandomAccess for Copied<I>
143+
where
144+
I: TrustedRandomAccess,
145+
{
146+
#[inline]
147+
fn may_have_side_effect() -> bool {
148+
I::may_have_side_effect()
149+
}
150+
}
151+
152+
#[stable(feature = "iter_copied", since = "1.36.0")]
153+
unsafe impl<'a, I, T: 'a> TrustedLen for Copied<I>
154+
where
155+
I: TrustedLen<Item = &'a T>,
156+
T: Copy,
157+
{
158+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
use crate::{iter::FusedIterator, ops::Try};
2+
3+
/// An iterator that repeats endlessly.
4+
///
5+
/// This `struct` is created by the [`cycle`] method on [`Iterator`]. See its
6+
/// documentation for more.
7+
///
8+
/// [`cycle`]: Iterator::cycle
9+
/// [`Iterator`]: trait.Iterator.html
10+
#[derive(Clone, Debug)]
11+
#[must_use = "iterators are lazy and do nothing unless consumed"]
12+
#[stable(feature = "rust1", since = "1.0.0")]
13+
pub struct Cycle<I> {
14+
orig: I,
15+
iter: I,
16+
}
17+
18+
impl<I: Clone> Cycle<I> {
19+
pub(in crate::iter) fn new(iter: I) -> Cycle<I> {
20+
Cycle { orig: iter.clone(), iter }
21+
}
22+
}
23+
24+
#[stable(feature = "rust1", since = "1.0.0")]
25+
impl<I> Iterator for Cycle<I>
26+
where
27+
I: Clone + Iterator,
28+
{
29+
type Item = <I as Iterator>::Item;
30+
31+
#[inline]
32+
fn next(&mut self) -> Option<<I as Iterator>::Item> {
33+
match self.iter.next() {
34+
None => {
35+
self.iter = self.orig.clone();
36+
self.iter.next()
37+
}
38+
y => y,
39+
}
40+
}
41+
42+
#[inline]
43+
fn size_hint(&self) -> (usize, Option<usize>) {
44+
// the cycle iterator is either empty or infinite
45+
match self.orig.size_hint() {
46+
sz @ (0, Some(0)) => sz,
47+
(0, _) => (0, None),
48+
_ => (usize::MAX, None),
49+
}
50+
}
51+
52+
#[inline]
53+
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
54+
where
55+
F: FnMut(Acc, Self::Item) -> R,
56+
R: Try<Ok = Acc>,
57+
{
58+
// fully iterate the current iterator. this is necessary because
59+
// `self.iter` may be empty even when `self.orig` isn't
60+
acc = self.iter.try_fold(acc, &mut f)?;
61+
self.iter = self.orig.clone();
62+
63+
// complete a full cycle, keeping track of whether the cycled
64+
// iterator is empty or not. we need to return early in case
65+
// of an empty iterator to prevent an infinite loop
66+
let mut is_empty = true;
67+
acc = self.iter.try_fold(acc, |acc, x| {
68+
is_empty = false;
69+
f(acc, x)
70+
})?;
71+
72+
if is_empty {
73+
return try { acc };
74+
}
75+
76+
loop {
77+
self.iter = self.orig.clone();
78+
acc = self.iter.try_fold(acc, &mut f)?;
79+
}
80+
}
81+
82+
// No `fold` override, because `fold` doesn't make much sense for `Cycle`,
83+
// and we can't do anything better than the default.
84+
}
85+
86+
#[stable(feature = "fused", since = "1.26.0")]
87+
impl<I> FusedIterator for Cycle<I> where I: Clone + Iterator {}

0 commit comments

Comments
 (0)