core/iter/adapters/
cloned.rs

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