repeat_n.rs - source (original) (raw)
core/iter/sources/
repeat_n.rs
1use crate::fmt;
2use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
3use crate::mem::MaybeUninit;
4use crate::num::NonZero;
5use crate::ops::{NeverShortCircuit, Try};
6
7/// Creates a new iterator that repeats a single element a given number of times.
8///
9/// The `repeat_n()` function repeats a single value exactly `n` times.
10///
11/// This is very similar to using [`repeat()`] with [`Iterator::take()`],
12/// but `repeat_n()` can return the original value, rather than always cloning.
13///
14/// [`repeat()`]: crate::iter::repeat
15///
16/// # Examples
17///
18/// Basic usage:
19///
20/// ```
21/// use std::iter;
22///
23/// // four of the number four:
24/// let mut four_fours = iter::repeat_n(4, 4);
25///
26/// assert_eq!(Some(4), four_fours.next());
27/// assert_eq!(Some(4), four_fours.next());
28/// assert_eq!(Some(4), four_fours.next());
29/// assert_eq!(Some(4), four_fours.next());
30///
31/// // no more fours
32/// assert_eq!(None, four_fours.next());
33/// ```
34///
35/// For non-`Copy` types,
36///
37/// ```
38/// use std::iter;
39///
40/// let v: Vec<i32> = Vec::with_capacity(123);
41/// let mut it = iter::repeat_n(v, 5);
42///
43/// for i in 0..4 {
44/// // It starts by cloning things
45/// let cloned = it.next().unwrap();
46/// assert_eq!(cloned.len(), 0);
47/// assert_eq!(cloned.capacity(), 0);
48/// }
49///
50/// // ... but the last item is the original one
51/// let last = it.next().unwrap();
52/// assert_eq!(last.len(), 0);
53/// assert_eq!(last.capacity(), 123);
54///
55/// // ... and now we're done
56/// assert_eq!(None, it.next());
57/// ```
58#[inline]
59#[stable(feature = "iter_repeat_n", since = "1.82.0")]
60pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
61 let element = if count == 0 {
62 // `element` gets dropped eagerly.
63 MaybeUninit::uninit()
64 } else {
65 MaybeUninit::new(element)
66 };
67
68 RepeatN { element, count }
69}
70
71/// An iterator that repeats an element an exact number of times.
72///
73/// This `struct` is created by the [`repeat_n()`] function.
74/// See its documentation for more.
75#[stable(feature = "iter_repeat_n", since = "1.82.0")]
76pub struct RepeatN<A> {
77 count: usize,
78 // Invariant: uninit iff count == 0.
79 element: MaybeUninit<A>,
80}
81
82impl<A> RepeatN<A> {
83 /// Returns the element if it hasn't been dropped already.
84 fn element_ref(&self) -> Option<&A> {
85 if self.count > 0 {
86 // SAFETY: The count is non-zero, so it must be initialized.
87 Some(unsafe { self.element.assume_init_ref() })
88 } else {
89 None
90 }
91 }
92 /// If we haven't already dropped the element, return it in an option.
93 ///
94 /// Clears the count so it won't be dropped again later.
95 #[inline]
96 fn take_element(&mut self) -> Option<A> {
97 if self.count > 0 {
98 self.count = 0;
99 // SAFETY: We just set count to zero so it won't be dropped again,
100 // and it used to be non-zero so it hasn't already been dropped.
101 let element = unsafe { self.element.assume_init_read() };
102 Some(element)
103 } else {
104 None
105 }
106 }
107}
108
109#[stable(feature = "iter_repeat_n", since = "1.82.0")]
110impl<A: Clone> Clone for RepeatN<A> {
111 fn clone(&self) -> RepeatN<A> {
112 RepeatN {
113 count: self.count,
114 element: self.element_ref().cloned().map_or_else(MaybeUninit::uninit, MaybeUninit::new),
115 }
116 }
117}
118
119#[stable(feature = "iter_repeat_n", since = "1.82.0")]
120impl<A: fmt::Debug> fmt::Debug for RepeatN<A> {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 f.debug_struct("RepeatN")
123 .field("count", &self.count)
124 .field("element", &self.element_ref())
125 .finish()
126 }
127}
128
129#[stable(feature = "iter_repeat_n", since = "1.82.0")]
130impl<A> Drop for RepeatN<A> {
131 fn drop(&mut self) {
132 self.take_element();
133 }
134}
135
136#[stable(feature = "iter_repeat_n", since = "1.82.0")]
137impl<A: Clone> Iterator for RepeatN<A> {
138 type Item = A;
139
140 #[inline]
141 fn next(&mut self) -> Option<A> {
142 if self.count > 0 {
143 // SAFETY: Just checked it's not empty
144 unsafe { Some(self.next_unchecked()) }
145 } else {
146 None
147 }
148 }
149
150 #[inline]
151 fn size_hint(&self) -> (usize, Option<usize>) {
152 let len = self.len();
153 (len, Some(len))
154 }
155
156 #[inline]
157 fn advance_by(&mut self, skip: usize) -> Result<(), NonZero<usize>> {
158 let len = self.count;
159
160 if skip >= len {
161 self.take_element();
162 }
163
164 if skip > len {
165 // SAFETY: we just checked that the difference is positive
166 Err(unsafe { NonZero::new_unchecked(skip - len) })
167 } else {
168 self.count = len - skip;
169 Ok(())
170 }
171 }
172
173 fn try_fold<B, F, R>(&mut self, mut acc: B, mut f: F) -> R
174 where
175 F: FnMut(B, A) -> R,
176 R: Try<Output = B>,
177 {
178 if self.count > 0 {
179 while self.count > 1 {
180 self.count -= 1;
181 // SAFETY: the count was larger than 1, so the element is
182 // initialized and hasn't been dropped.
183 acc = f(acc, unsafe { self.element.assume_init_ref().clone() })?;
184 }
185
186 // We could just set the count to zero directly, but doing it this
187 // way should make it easier for the optimizer to fold this tail
188 // into the loop when `clone()` is equivalent to copying.
189 self.count -= 1;
190 // SAFETY: we just set the count to zero from one, so the element
191 // is still initialized, has not been dropped yet and will not be
192 // accessed by future calls.
193 f(acc, unsafe { self.element.assume_init_read() })
194 } else {
195 try { acc }
196 }
197 }
198
199 fn fold<B, F>(mut self, init: B, f: F) -> B
200 where
201 F: FnMut(B, A) -> B,
202 {
203 self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
204 }
205
206 #[inline]
207 fn last(mut self) -> Option<A> {
208 self.take_element()
209 }
210
211 #[inline]
212 fn count(self) -> usize {
213 self.len()
214 }
215}
216
217#[stable(feature = "iter_repeat_n", since = "1.82.0")]
218impl<A: Clone> ExactSizeIterator for RepeatN<A> {
219 fn len(&self) -> usize {
220 self.count
221 }
222}
223
224#[stable(feature = "iter_repeat_n", since = "1.82.0")]
225impl<A: Clone> DoubleEndedIterator for RepeatN<A> {
226 #[inline]
227 fn next_back(&mut self) -> Option<A> {
228 self.next()
229 }
230
231 #[inline]
232 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {
233 self.advance_by(n)
234 }
235
236 #[inline]
237 fn nth_back(&mut self, n: usize) -> Option<A> {
238 self.nth(n)
239 }
240
241 #[inline]
242 fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R
243 where
244 F: FnMut(B, A) -> R,
245 R: Try<Output = B>,
246 {
247 self.try_fold(init, f)
248 }
249
250 #[inline]
251 fn rfold<B, F>(self, init: B, f: F) -> B
252 where
253 F: FnMut(B, A) -> B,
254 {
255 self.fold(init, f)
256 }
257}
258
259#[stable(feature = "iter_repeat_n", since = "1.82.0")]
260impl<A: Clone> FusedIterator for RepeatN<A> {}
261
262#[unstable(feature = "trusted_len", issue = "37572")]
263unsafe impl<A: Clone> TrustedLen for RepeatN<A> {}
264#[stable(feature = "iter_repeat_n", since = "1.82.0")]
265impl<A: Clone> UncheckedIterator for RepeatN<A> {
266 #[inline]
267 unsafe fn next_unchecked(&mut self) -> Self::Item {
268 // SAFETY: The caller promised the iterator isn't empty
269 self.count = unsafe { self.count.unchecked_sub(1) };
270 if self.count == 0 {
271 // SAFETY: the check above ensured that the count used to be non-zero,
272 // so element hasn't been dropped yet, and we just lowered the count to
273 // zero so it won't be dropped later, and thus it's okay to take it here.
274 unsafe { self.element.assume_init_read() }
275 } else {
276 // SAFETY: the count is non-zero, so it must have not been dropped yet.
277 let element = unsafe { self.element.assume_init_ref() };
278 A::clone(element)
279 }
280 }
281}