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