1use core::num::NonZero;
2
3use crate::cmp::Ordering;
4use crate::iter::adapters::zip::try_get_unchecked;
5use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
6use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
7use crate::ops::Try;
8
9#[stable(feature = "iter_cloned", since = "1.1.0")]
17#[must_use = "iterators are lazy and do nothing unless consumed"]
18#[derive(Clone, Debug)]
19pub struct Cloned<I> {
20 it: I,
21}
22
23impl<I> Cloned<I> {
24 pub(in crate::iter) fn new(it: I) -> Cloned<I> {
25 Cloned { it }
26 }
27}
28
29fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
30 move |acc, elt| f(acc, elt.clone())
31}
32
33#[stable(feature = "iter_cloned", since = "1.1.0")]
34impl<'a, I, T: 'a> Iterator for Cloned<I>
35where
36 I: Iterator<Item = &'a T>,
37 T: Clone,
38{
39 type Item = T;
40
41 fn next(&mut self) -> Option<T> {
42 self.it.next().cloned()
43 }
44
45 #[inline]
46 fn size_hint(&self) -> (usize, Option<usize>) {
47 self.it.size_hint()
48 }
49
50 #[inline]
51 fn count(self) -> usize {
52 self.it.count()
53 }
54
55 fn last(self) -> Option<T> {
56 self.it.last().cloned()
57 }
58
59 #[inline]
60 fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
61 self.it.advance_by(n)
62 }
63
64 fn nth(&mut self, n: usize) -> Option<T> {
65 self.it.nth(n).cloned()
66 }
67
68 fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
69 where
70 F: FnMut(B, Self::Item) -> R,
71 R: Try<Output = B>,
72 {
73 self.it.try_fold(init, clone_try_fold(f))
74 }
75
76 fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
77 where
78 F: FnMut(Acc, Self::Item) -> Acc,
79 {
80 self.it.map(T::clone).fold(init, f)
81 }
82
83 fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
84 where
85 P: FnMut(&Self::Item) -> bool,
86 {
87 self.it.find(move |x| predicate(&x)).cloned()
88 }
89
90 fn max_by<F>(self, mut compare: F) -> Option<Self::Item>
91 where
92 F: FnMut(&Self::Item, &Self::Item) -> Ordering,
93 {
94 self.it.max_by(move |&x, &y| compare(x, y)).cloned()
95 }
96
97 fn min_by<F>(self, mut compare: F) -> Option<Self::Item>
98 where
99 F: FnMut(&Self::Item, &Self::Item) -> Ordering,
100 {
101 self.it.min_by(move |&x, &y| compare(x, y)).cloned()
102 }
103
104 fn cmp<O>(self, other: O) -> Ordering
105 where
106 O: IntoIterator<Item = Self::Item>,
107 Self::Item: Ord,
108 {
109 self.it.cmp_by(other, |x, y| x.cmp(&y))
110 }
111
112 fn partial_cmp<O>(self, other: O) -> Option<Ordering>
113 where
114 O: IntoIterator,
115 Self::Item: PartialOrd<O::Item>,
116 {
117 self.it.partial_cmp_by(other, |x, y| x.partial_cmp(&y))
118 }
119
120 fn eq<O>(self, other: O) -> bool
121 where
122 O: IntoIterator,
123 Self::Item: PartialEq<O::Item>,
124 {
125 self.it.eq_by(other, |x, y| x == &y)
126 }
127
128 fn is_sorted_by<F>(self, mut compare: F) -> bool
129 where
130 F: FnMut(&Self::Item, &Self::Item) -> bool,
131 {
132 self.it.is_sorted_by(move |&x, &y| compare(x, y))
133 }
134
135 unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
136 where
137 Self: TrustedRandomAccessNoCoerce,
138 {
139 unsafe { try_get_unchecked(&mut self.it, idx).clone() }
142 }
143}
144
145#[stable(feature = "iter_cloned", since = "1.1.0")]
146impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
147where
148 I: DoubleEndedIterator<Item = &'a T>,
149 T: Clone,
150{
151 fn next_back(&mut self) -> Option<T> {
152 self.it.next_back().cloned()
153 }
154
155 #[inline]
156 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
157 self.it.advance_back_by(n)
158 }
159
160 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
161 where
162 F: FnMut(B, Self::Item) -> R,
163 R: Try<Output = B>,
164 {
165 self.it.try_rfold(init, clone_try_fold(f))
166 }
167
168 fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
169 where
170 F: FnMut(Acc, Self::Item) -> Acc,
171 {
172 self.it.map(T::clone).rfold(init, f)
173 }
174
175 fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
176 where
177 P: FnMut(&Self::Item) -> bool,
178 {
179 self.it.rfind(move |x| predicate(&x)).cloned()
180 }
181}
182
183#[stable(feature = "iter_cloned", since = "1.1.0")]
184impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
185where
186 I: ExactSizeIterator<Item = &'a T>,
187 T: Clone,
188{
189 #[inline]
190 fn len(&self) -> usize {
191 self.it.len()
192 }
193
194 #[inline]
195 fn is_empty(&self) -> bool {
196 self.it.is_empty()
197 }
198}
199
200#[stable(feature = "fused", since = "1.26.0")]
201impl<'a, I, T: 'a> FusedIterator for Cloned<I>
202where
203 I: FusedIterator<Item = &'a T>,
204 T: Clone,
205{
206}
207
208#[doc(hidden)]
209#[unstable(feature = "trusted_random_access", issue = "none")]
210unsafe impl<I> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess {}
211
212#[doc(hidden)]
213#[unstable(feature = "trusted_random_access", issue = "none")]
214unsafe impl<I> TrustedRandomAccessNoCoerce for Cloned<I>
215where
216 I: TrustedRandomAccessNoCoerce,
217{
218 const MAY_HAVE_SIDE_EFFECT: bool = true;
219}
220
221#[unstable(feature = "trusted_len", issue = "37572")]
222unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
223where
224 I: TrustedLen<Item = &'a T>,
225 T: Clone,
226{
227}
228
229impl<'a, I, T: 'a> UncheckedIterator for Cloned<I>
230where
231 I: UncheckedIterator<Item = &'a T>,
232 T: Clone,
233{
234 unsafe fn next_unchecked(&mut self) -> T {
235 let item = unsafe { self.it.next_unchecked() };
238 item.clone()
239 }
240}
241
242#[stable(feature = "default_iters", since = "1.70.0")]
243impl<I: Default> Default for Cloned<I> {
244 fn default() -> Self {
252 Self::new(Default::default())
253 }
254}
255
256#[unstable(issue = "none", feature = "inplace_iteration")]
257unsafe impl<I> SourceIter for Cloned<I>
258where
259 I: SourceIter,
260{
261 type Source = I::Source;
262
263 #[inline]
264 unsafe fn as_inner(&mut self) -> &mut I::Source {
265 unsafe { SourceIter::as_inner(&mut self.it) }
267 }
268}
269
270#[unstable(issue = "none", feature = "inplace_iteration")]
271unsafe impl<I: InPlaceIterable> InPlaceIterable for Cloned<I> {
272 const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
273 const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
274}