]> git.lizzy.rs Git - rust.git/blob - library/core/src/iter/adapters/cloned.rs
7efc155175c34f8c2d4ad0d73cc2e8654562400e
[rust.git] / library / core / src / iter / adapters / cloned.rs
1 use crate::iter::adapters::{zip::try_get_unchecked, TrustedRandomAccess};
2 use crate::iter::{FusedIterator, TrustedLen};
3 use crate::ops::Try;
4
5 /// An iterator that clones the elements of an underlying iterator.
6 ///
7 /// This `struct` is created by the [`cloned`] method on [`Iterator`]. See its
8 /// documentation for more.
9 ///
10 /// [`cloned`]: Iterator::cloned
11 /// [`Iterator`]: trait.Iterator.html
12 #[stable(feature = "iter_cloned", since = "1.1.0")]
13 #[must_use = "iterators are lazy and do nothing unless consumed"]
14 #[derive(Clone, Debug)]
15 pub struct Cloned<I> {
16     it: I,
17 }
18
19 impl<I> Cloned<I> {
20     pub(in crate::iter) fn new(it: I) -> Cloned<I> {
21         Cloned { it }
22     }
23 }
24
25 fn clone_try_fold<T: Clone, Acc, R>(mut f: impl FnMut(Acc, T) -> R) -> impl FnMut(Acc, &T) -> R {
26     move |acc, elt| f(acc, elt.clone())
27 }
28
29 #[stable(feature = "iter_cloned", since = "1.1.0")]
30 impl<'a, I, T: 'a> Iterator for Cloned<I>
31 where
32     I: Iterator<Item = &'a T>,
33     T: Clone,
34 {
35     type Item = T;
36
37     fn next(&mut self) -> Option<T> {
38         self.it.next().cloned()
39     }
40
41     fn size_hint(&self) -> (usize, Option<usize>) {
42         self.it.size_hint()
43     }
44
45     fn try_fold<B, F, R>(&mut self, init: B, f: F) -> R
46     where
47         Self: Sized,
48         F: FnMut(B, Self::Item) -> R,
49         R: Try<Output = B>,
50     {
51         self.it.try_fold(init, clone_try_fold(f))
52     }
53
54     fn fold<Acc, F>(self, init: Acc, f: F) -> Acc
55     where
56         F: FnMut(Acc, Self::Item) -> Acc,
57     {
58         self.it.map(T::clone).fold(init, f)
59     }
60
61     unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> T
62     where
63         Self: TrustedRandomAccess,
64     {
65         // SAFETY: the caller must uphold the contract for
66         // `Iterator::__iterator_get_unchecked`.
67         unsafe { try_get_unchecked(&mut self.it, idx).clone() }
68     }
69 }
70
71 #[stable(feature = "iter_cloned", since = "1.1.0")]
72 impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
73 where
74     I: DoubleEndedIterator<Item = &'a T>,
75     T: Clone,
76 {
77     fn next_back(&mut self) -> Option<T> {
78         self.it.next_back().cloned()
79     }
80
81     fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
82     where
83         Self: Sized,
84         F: FnMut(B, Self::Item) -> R,
85         R: Try<Output = B>,
86     {
87         self.it.try_rfold(init, clone_try_fold(f))
88     }
89
90     fn rfold<Acc, F>(self, init: Acc, f: F) -> Acc
91     where
92         F: FnMut(Acc, Self::Item) -> Acc,
93     {
94         self.it.map(T::clone).rfold(init, f)
95     }
96 }
97
98 #[stable(feature = "iter_cloned", since = "1.1.0")]
99 impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
100 where
101     I: ExactSizeIterator<Item = &'a T>,
102     T: Clone,
103 {
104     fn len(&self) -> usize {
105         self.it.len()
106     }
107
108     fn is_empty(&self) -> bool {
109         self.it.is_empty()
110     }
111 }
112
113 #[stable(feature = "fused", since = "1.26.0")]
114 impl<'a, I, T: 'a> FusedIterator for Cloned<I>
115 where
116     I: FusedIterator<Item = &'a T>,
117     T: Clone,
118 {
119 }
120
121 #[doc(hidden)]
122 #[unstable(feature = "trusted_random_access", issue = "none")]
123 unsafe impl<I> TrustedRandomAccess for Cloned<I>
124 where
125     I: TrustedRandomAccess,
126 {
127     const MAY_HAVE_SIDE_EFFECT: bool = true;
128 }
129
130 #[unstable(feature = "trusted_len", issue = "37572")]
131 unsafe impl<'a, I, T: 'a> TrustedLen for Cloned<I>
132 where
133     I: TrustedLen<Item = &'a T>,
134     T: Clone,
135 {
136 }