Skip to main content

core/iter/adapters/
cloned.rs

1#[cfg(not(feature = "ferrocene_subset"))]
2use core::num::NonZero;
3
4#[cfg(not(feature = "ferrocene_subset"))]
5use crate::iter::adapters::zip::try_get_unchecked;
6#[cfg(not(feature = "ferrocene_subset"))]
7use crate::iter::adapters::{SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
8#[cfg(not(feature = "ferrocene_subset"))]
9use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
10use crate::ops::Try;
11
12// Ferrocene addition: imports for certified subset
13#[cfg(feature = "ferrocene_subset")]
14#[rustfmt::skip]
15use crate::iter::{TrustedLen, UncheckedIterator};
16
17/// An iterator that clones the elements of an underlying iterator.
18///
19/// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
20/// documentation for more.
21///
22/// [`cloned`]: Iterator::cloned
23/// [`Iterator`]: trait.Iterator.html
24#[stable(feature = "iter_cloned", since = "1.1.0")]
25#[must_use = "iterators are lazy and do nothing unless consumed"]
26#[derive(Clone, Debug)]
27pub struct Cloned<I> {
28    it: I,
29}
30
31impl<I> Cloned<I> {
32    pub(in crate::iter) fn new(it: I) -> Cloned<I> {
33        Cloned { it }
34    }
35}
36
37fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
38    move |acc, elt| f(acc, elt.clone())
39}
40
41#[stable(feature = "iter_cloned", since = "1.1.0")]
42impl<'a, I, T: 'a> Iterator for Cloned<I>
43where
44    I: Iterator<Item = &'a T>,
45    T: Clone,
46{
47    type Item = T;
48
49    fn next(&mut self) -> Option<T> {
50        self.it.next().cloned()
51    }
52
53    fn size_hint(&self) -> (usize, Option<usize>) {
54        self.it.size_hint()
55    }
56
57    fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
58    where
59        Self: Sized,
60        F: FnMut(B, Self::Item) -> R,
61        R: Try<Output = B>,
62    {
63        self.it.try_fold(init, clone_try_fold(f))
64    }
65
66    fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
67    where
68        F: FnMut(Acc, Self::Item) -> Acc,
69    {
70        self.it.map(T::clone).fold(init, f)
71    }
72
73    #[cfg(not(feature = "ferrocene_subset"))]
74    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
75    where
76        Self: TrustedRandomAccessNoCoerce,
77    {
78        // SAFETY: the caller must uphold the contract for
79        // `Iterator::__iterator_get_unchecked`.
80        unsafe { try_get_unchecked(&mut self.it, idx).clone() }
81    }
82}
83
84#[stable(feature = "iter_cloned", since = "1.1.0")]
85impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
86where
87    I: DoubleEndedIterator<Item = &'a T>,
88    T: Clone,
89{
90    fn next_back(&mut self) -> Option<T> {
91        self.it.next_back().cloned()
92    }
93
94    fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
95    where
96        Self: Sized,
97        F: FnMut(B, Self::Item) -> R,
98        R: Try<Output = B>,
99    {
100        self.it.try_rfold(init, clone_try_fold(f))
101    }
102
103    fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
104    where
105        F: FnMut(Acc, Self::Item) -> Acc,
106    {
107        self.it.map(T::clone).rfold(init, f)
108    }
109}
110
111#[stable(feature = "iter_cloned", since = "1.1.0")]
112#[cfg(not(feature = "ferrocene_subset"))]
113impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
114where
115    I: ExactSizeIterator<Item = &'a T>,
116    T: Clone,
117{
118    fn len(&self) -> usize {
119        self.it.len()
120    }
121
122    fn is_empty(&self) -> bool {
123        self.it.is_empty()
124    }
125}
126
127#[stable(feature = "fused", since = "1.26.0")]
128#[cfg(not(feature = "ferrocene_subset"))]
129impl<'a, I, T: 'a> FusedIterator for Cloned<I>
130where
131    I: FusedIterator<Item = &'a T>,
132    T: Clone,
133{
134}
135
136#[doc(hidden)]
137#[unstable(feature = "trusted_random_access", issue = "none")]
138#[cfg(not(feature = "ferrocene_subset"))]
139unsafe impl<I> TrustedRandomAccess for Cloned<I> where I: TrustedRandomAccess {}
140
141#[doc(hidden)]
142#[unstable(feature = "trusted_random_access", issue = "none")]
143#[cfg(not(feature = "ferrocene_subset"))]
144unsafe impl<I> TrustedRandomAccessNoCoerce for Cloned<I>
145where
146    I: TrustedRandomAccessNoCoerce,
147{
148    const MAY_HAVE_SIDE_EFFECT: bool = true;
149}
150
151#[unstable(feature = "trusted_len", issue = "37572")]
152unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
153where
154    I: TrustedLen<Item = &'a T>,
155    T: Clone,
156{
157}
158
159impl<'a, I, T: 'a> UncheckedIterator for Cloned<I>
160where
161    I: UncheckedIterator<Item = &'a T>,
162    T: Clone,
163{
164    unsafe fn next_unchecked(&mut self) -> T {
165        // SAFETY: `Cloned` is 1:1 with the inner iterator, so if the caller promised
166        // that there's an element left, the inner iterator has one too.
167        let item = unsafe { self.it.next_unchecked() };
168        item.clone()
169    }
170}
171
172#[stable(feature = "default_iters", since = "1.70.0")]
173#[cfg(not(feature = "ferrocene_subset"))]
174impl<I: Default> Default for Cloned<I> {
175    /// Creates a `Cloned` iterator from the default value of `I`
176    /// ```
177    /// # use core::slice;
178    /// # use core::iter::Cloned;
179    /// let iter: Cloned<slice::Iter<'_, u8>> = Default::default();
180    /// assert_eq!(iter.len(), 0);
181    /// ```
182    fn default() -> Self {
183        Self::new(Default::default())
184    }
185}
186
187#[unstable(issue = "none", feature = "inplace_iteration")]
188#[cfg(not(feature = "ferrocene_subset"))]
189unsafe impl<I> SourceIter for Cloned<I>
190where
191    I: SourceIter,
192{
193    type Source = I::Source;
194
195    #[inline]
196    unsafe fn as_inner(&mut self) -> &mut I::Source {
197        // SAFETY: unsafe function forwarding to unsafe function with the same requirements
198        unsafe { SourceIter::as_inner(&mut self.it) }
199    }
200}
201
202#[unstable(issue = "none", feature = "inplace_iteration")]
203#[cfg(not(feature = "ferrocene_subset"))]
204unsafe impl<I: InPlaceIterable> InPlaceIterable for Cloned<I> {
205    const EXPAND_BY: Option<NonZero<usize>> = I::EXPAND_BY;
206    const MERGE_BY: Option<NonZero<usize>> = I::MERGE_BY;
207}