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