rayon/iter/
repeat.rs

1use super::plumbing::*;
2use super::*;
3use std::num::NonZeroUsize;
4use std::{fmt, iter, mem};
5
6/// Iterator adaptor for [the `repeat()` function].
7///
8/// [the `repeat()` function]: repeat()
9#[derive(Debug, Clone)]
10pub struct Repeat<T> {
11    element: T,
12}
13
14/// Creates a parallel iterator that endlessly repeats `element` (by
15/// cloning it). Note that this iterator has "infinite" length, so
16/// typically you would want to use `zip` or `take` or some other
17/// means to shorten it, or consider using
18/// [the `repeat_n()` function] instead.
19///
20/// [the `repeat_n()` function]: repeat_n()
21///
22/// # Examples
23///
24/// ```
25/// use rayon::prelude::*;
26/// use rayon::iter::repeat;
27/// let x: Vec<(i32, i32)> = repeat(22).zip(0..3).collect();
28/// assert_eq!(x, vec![(22, 0), (22, 1), (22, 2)]);
29/// ```
30pub fn repeat<T: Clone + Send>(element: T) -> Repeat<T> {
31    Repeat { element }
32}
33
34impl<T> Repeat<T>
35where
36    T: Clone + Send,
37{
38    /// Takes only `n` repeats of the element, similar to the general
39    /// [`take()`].
40    ///
41    /// The resulting `RepeatN` is an `IndexedParallelIterator`, allowing
42    /// more functionality than `Repeat` alone.
43    ///
44    /// [`take()`]: IndexedParallelIterator::take()
45    pub fn take(self, n: usize) -> RepeatN<T> {
46        repeat_n(self.element, n)
47    }
48
49    /// Iterates tuples, repeating the element with items from another
50    /// iterator, similar to the general [`zip()`].
51    ///
52    /// [`zip()`]: IndexedParallelIterator::zip()
53    pub fn zip<Z>(self, zip_op: Z) -> Zip<RepeatN<T>, Z::Iter>
54    where
55        Z: IntoParallelIterator<Iter: IndexedParallelIterator>,
56    {
57        let z = zip_op.into_par_iter();
58        let n = z.len();
59        self.take(n).zip(z)
60    }
61}
62
63impl<T> ParallelIterator for Repeat<T>
64where
65    T: Clone + Send,
66{
67    type Item = T;
68
69    fn drive_unindexed<C>(self, consumer: C) -> C::Result
70    where
71        C: UnindexedConsumer<Self::Item>,
72    {
73        let producer = RepeatProducer {
74            element: self.element,
75        };
76        bridge_unindexed(producer, consumer)
77    }
78}
79
80/// Unindexed producer for `Repeat`.
81struct RepeatProducer<T: Clone + Send> {
82    element: T,
83}
84
85impl<T: Clone + Send> UnindexedProducer for RepeatProducer<T> {
86    type Item = T;
87
88    fn split(self) -> (Self, Option<Self>) {
89        (
90            RepeatProducer {
91                element: self.element.clone(),
92            },
93            Some(RepeatProducer {
94                element: self.element,
95            }),
96        )
97    }
98
99    fn fold_with<F>(self, folder: F) -> F
100    where
101        F: Folder<T>,
102    {
103        folder.consume_iter(iter::repeat(self.element))
104    }
105}
106
107/// Iterator adaptor for [the `repeat_n()` function].
108///
109/// [the `repeat_n()` function]: repeat_n()
110#[derive(Clone)]
111pub struct RepeatN<T> {
112    inner: RepeatNProducer<T>,
113}
114
115/// Creates a parallel iterator that produces `n` repeats of `element`
116/// (by cloning it).
117///
118/// # Examples
119///
120/// ```
121/// use rayon::prelude::*;
122/// use rayon::iter::repeat_n;
123/// let x: Vec<(i32, i32)> = repeat_n(22, 3).zip(0..3).collect();
124/// assert_eq!(x, vec![(22, 0), (22, 1), (22, 2)]);
125/// ```
126pub fn repeat_n<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {
127    let inner = match NonZeroUsize::new(n) {
128        Some(count) => RepeatNProducer::Repeats(element, count),
129        None => RepeatNProducer::Empty,
130    };
131    RepeatN { inner }
132}
133
134/// Creates a parallel iterator that produces `n` repeats of `element`
135/// (by cloning it).
136///
137/// Deprecated in favor of [`repeat_n`] for consistency with the standard library.
138#[deprecated(note = "use `repeat_n`")]
139pub fn repeatn<T: Clone + Send>(element: T, n: usize) -> RepeatN<T> {
140    repeat_n(element, n)
141}
142
143impl<T: fmt::Debug> fmt::Debug for RepeatN<T> {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        let mut dbg = f.debug_struct("RepeatN");
146        if let RepeatNProducer::Repeats(element, count) = &self.inner {
147            dbg.field("count", &count.get())
148                .field("element", element)
149                .finish()
150        } else {
151            dbg.field("count", &0usize).finish_non_exhaustive()
152        }
153    }
154}
155
156impl<T> ParallelIterator for RepeatN<T>
157where
158    T: Clone + Send,
159{
160    type Item = T;
161
162    fn drive_unindexed<C>(self, consumer: C) -> C::Result
163    where
164        C: UnindexedConsumer<Self::Item>,
165    {
166        bridge(self, consumer)
167    }
168
169    fn opt_len(&self) -> Option<usize> {
170        Some(self.inner.len())
171    }
172}
173
174impl<T> IndexedParallelIterator for RepeatN<T>
175where
176    T: Clone + Send,
177{
178    fn drive<C>(self, consumer: C) -> C::Result
179    where
180        C: Consumer<Self::Item>,
181    {
182        bridge(self, consumer)
183    }
184
185    fn with_producer<CB>(self, callback: CB) -> CB::Output
186    where
187        CB: ProducerCallback<Self::Item>,
188    {
189        callback.callback(self.inner)
190    }
191
192    fn len(&self) -> usize {
193        self.inner.len()
194    }
195}
196
197/// Producer for `RepeatN`.
198#[derive(Clone)]
199enum RepeatNProducer<T> {
200    Repeats(T, NonZeroUsize),
201    Empty,
202}
203
204impl<T: Clone + Send> Producer for RepeatNProducer<T> {
205    type Item = T;
206    type IntoIter = Self;
207
208    fn into_iter(self) -> Self::IntoIter {
209        // We could potentially use `std::iter::RepeatN` with MSRV 1.82, but we have no way to
210        // create an empty instance without a value in hand, like `repeat_n(value, 0)`.
211        self
212    }
213
214    fn split_at(self, index: usize) -> (Self, Self) {
215        if let Self::Repeats(element, count) = self {
216            assert!(index <= count.get());
217            match (
218                NonZeroUsize::new(index),
219                NonZeroUsize::new(count.get() - index),
220            ) {
221                (Some(left), Some(right)) => (
222                    Self::Repeats(element.clone(), left),
223                    Self::Repeats(element, right),
224                ),
225                (Some(left), None) => (Self::Repeats(element, left), Self::Empty),
226                (None, Some(right)) => (Self::Empty, Self::Repeats(element, right)),
227                (None, None) => unreachable!(),
228            }
229        } else {
230            assert!(index == 0);
231            (Self::Empty, Self::Empty)
232        }
233    }
234}
235
236impl<T: Clone> Iterator for RepeatNProducer<T> {
237    type Item = T;
238
239    #[inline]
240    fn next(&mut self) -> Option<T> {
241        if let Self::Repeats(element, count) = self {
242            if let Some(rem) = NonZeroUsize::new(count.get() - 1) {
243                *count = rem;
244                Some(element.clone())
245            } else {
246                match mem::replace(self, Self::Empty) {
247                    Self::Repeats(element, _) => Some(element),
248                    Self::Empty => unreachable!(),
249                }
250            }
251        } else {
252            None
253        }
254    }
255
256    #[inline]
257    fn nth(&mut self, n: usize) -> Option<T> {
258        if let Self::Repeats(_, count) = self {
259            if let Some(rem) = NonZeroUsize::new(count.get().saturating_sub(n)) {
260                *count = rem;
261                return self.next();
262            }
263            *self = Self::Empty;
264        }
265        None
266    }
267
268    #[inline]
269    fn size_hint(&self) -> (usize, Option<usize>) {
270        let len = self.len();
271        (len, Some(len))
272    }
273}
274
275impl<T: Clone> DoubleEndedIterator for RepeatNProducer<T> {
276    #[inline]
277    fn next_back(&mut self) -> Option<T> {
278        self.next()
279    }
280
281    #[inline]
282    fn nth_back(&mut self, n: usize) -> Option<T> {
283        self.nth(n)
284    }
285}
286
287impl<T: Clone> ExactSizeIterator for RepeatNProducer<T> {
288    #[inline]
289    fn len(&self) -> usize {
290        match self {
291            Self::Repeats(_, count) => count.get(),
292            Self::Empty => 0,
293        }
294    }
295}