Skip to main content

core/iter/adapters/
cloned.rs

1use core::num::NonZero;
2
3use crate::iter::adapters::zip::try_get_unchecked;
4use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
5use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
6use crate::ops::Try;
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)]
18pub struct Cloned<I> {
19    it: I,
20}
21
22impl<I> Cloned<I> {
23    pub(in crate::iter) const fn new(it: I) -> Cloned<I> {
24        Cloned { it }
25    }
26}
27
28#[inline]
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    fn size_hint(&self) -> (usize, Option<usize>) {
46        self.it.size_hint()
47    }
48
49    #[inline]
50    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
51    where
52        Self: Sized,
53        F: FnMut(B, Self::Item) -> R,
54        R: Try<Output = B>,
55    {
56        self.it.try_fold(init, clone_try_fold(f))
57    }
58
59    #[inline]
60    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
61    where
62        F: FnMut(Acc, Self::Item) -> Acc,
63    {
64        self.it.map(T::clone).fold(init, f)
65    }
66
67    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
68    where
69        Self: TrustedRandomAccessNoCoerce,
70    {
71        // SAFETY: the caller must uphold the contract for
72        // `Iterator::__iterator_get_unchecked`.
73        unsafe { try_get_unchecked(&mut self.it, idx).clone() }
74    }
75}
76
77#[stable(feature = "iter_cloned", since = "1.1.0")]
78impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
79where
80    I: DoubleEndedIterator<Item = &'a T>,
81    T: Clone,
82{
83    fn next_back(&mut self) -> Option<T> {
84        self.it.next_back().cloned()
85    }
86
87    #[inline]
88    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
89    where
90        Self: Sized,
91        F: FnMut(B, Self::Item) -> R,
92        R: Try<Output = B>,
93    {
94        self.it.try_rfold(init, clone_try_fold(f))
95    }
96
97    #[inline]
98    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
99    where
100        F: FnMut(Acc, Self::Item) -> Acc,
101    {
102        self.it.map(T::clone).rfold(init, f)
103    }
104}
105
106#[stable(feature = "iter_cloned", since = "1.1.0")]
107impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
108where
109    I: ExactSizeIterator<Item = &'a T>,
110    T: Clone,
111{
112    fn len(&self) -> usize {
113        self.it.len()
114    }
115
116    fn is_empty(&self) -> bool {
117        self.it.is_empty()
118    }
119}
120
121#[stable(feature = "fused", since = "1.26.0")]
122impl<'a, I, T: 'a> FusedIterator for Cloned<I>
123where
124    I: FusedIterator<Item = &'a T>,
125    T: Clone,
126{
127}
128
129#[doc(hidden)]
130#[unstable(feature = "trusted_random_access", issue = "none")]
131unsafe impl<I> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess {}
132
133#[doc(hidden)]
134#[unstable(feature = "trusted_random_access", issue = "none")]
135unsafe impl<I> TrustedRandomAccessNoCoerce for Cloned<I>
136where
137    I: TrustedRandomAccessNoCoerce,
138{
139    const MAY_HAVE_SIDE_EFFECT: bool = true;
140}
141
142#[unstable(feature = "trusted_len", issue = "37572")]
143unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
144where
145    I: TrustedLen<Item = &'a T>,
146    T: Clone,
147{
148}
149
150#[stable(feature = "default_iters", since = "1.70.0")]
151impl<I: Default> Default for Cloned<I> {
152    /// Creates a `Cloned` iterator from the default value of `I`
153    /// ```
154    /// # use core::slice;
155    /// # use core::iter::Cloned;
156    /// let iter: Cloned<slice::Iter<'_, u8>> = Default::default();
157    /// assert_eq!(iter.len(), 0);
158    /// ```
159    fn default() -> Self {
160        Self::new(Default::default())
161    }
162}
163
164#[unstable(issue = "none", feature = "inplace_iteration")]
165unsafe impl<I> SourceIter for Cloned<I>
166where
167    I: SourceIter,
168{
169    type Source = I::Source;
170
171    #[inline]
172    unsafe fn as_inner(&mut self) -> &mut I::Source {
173        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
174        unsafe { SourceIter::as_inner(&mut self.it) }
175    }
176}
177
178#[unstable(issue = "none", feature = "inplace_iteration")]
179unsafe impl<I: InPlaceIterable> InPlaceIterable for Cloned<I> {
180    const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
181    const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
182}