par_iter/
range_inclusive.rs1use std::ops::RangeInclusive;
20
21use crate::iter::{plumbing::*, *};
22
23#[derive(Debug, Clone)]
46pub struct Iter<T> {
47 range: RangeInclusive<T>,
48}
49
50impl<T> Iter<T>
51where
52 RangeInclusive<T>: Eq,
53 T: Ord + Copy,
54{
55 fn bounds(&self) -> Option<(T, T)> {
63 let start = *self.range.start();
64 let end = *self.range.end();
65 if start <= end && self.range == (start..=end) {
66 Some((start, end))
70 } else {
71 None
72 }
73 }
74}
75
76impl<T> IntoParallelIterator for RangeInclusive<T>
78where
79 Iter<T>: ParallelIterator,
80{
81 type Item = <Iter<T> as ParallelIterator>::Item;
82 type Iter = Iter<T>;
83
84 fn into_par_iter(self) -> Self::Iter {
85 Iter { range: self }
86 }
87}
88
89mod private {
99 use super::*;
100
101 pub trait RangeInteger: Sized + Send {
103 private_decl! {}
104
105 fn drive_unindexed<C>(iter: Iter<Self>, consumer: C) -> C::Result
106 where
107 C: UnindexedConsumer<Self>;
108
109 fn opt_len(iter: &Iter<Self>) -> Option<usize>;
110 }
111
112 pub trait IndexedRangeInteger: RangeInteger {
114 private_decl! {}
115
116 fn drive<C>(iter: Iter<Self>, consumer: C) -> C::Result
117 where
118 C: Consumer<Self>;
119
120 fn len(iter: &Iter<Self>) -> usize;
121
122 fn with_producer<CB>(iter: Iter<Self>, callback: CB) -> CB::Output
123 where
124 CB: ProducerCallback<Self>;
125 }
126}
127use private::{IndexedRangeInteger, RangeInteger};
128
129impl<T: RangeInteger> ParallelIterator for Iter<T> {
130 type Item = T;
131
132 fn drive_unindexed<C>(self, consumer: C) -> C::Result
133 where
134 C: UnindexedConsumer<T>,
135 {
136 T::drive_unindexed(self, consumer)
137 }
138
139 #[inline]
140 fn opt_len(&self) -> Option<usize> {
141 T::opt_len(self)
142 }
143}
144
145impl<T: IndexedRangeInteger> IndexedParallelIterator for Iter<T> {
146 fn drive<C>(self, consumer: C) -> C::Result
147 where
148 C: Consumer<T>,
149 {
150 T::drive(self, consumer)
151 }
152
153 #[inline]
154 fn len(&self) -> usize {
155 T::len(self)
156 }
157
158 fn with_producer<CB>(self, callback: CB) -> CB::Output
159 where
160 CB: ProducerCallback<T>,
161 {
162 T::with_producer(self, callback)
163 }
164}
165
166macro_rules! convert {
167 ( $iter:ident . $method:ident ( $( $arg:expr ),* ) ) => {
168 if let Some((start, end)) = $iter.bounds() {
169 if let Some(end) = end.checked_add(1) {
170 (start..end).into_par_iter().$method($( $arg ),*)
171 } else {
172 (start..end).into_par_iter().chain(once(end)).$method($( $arg ),*)
173 }
174 } else {
175 empty::<Self>().$method($( $arg ),*)
176 }
177 };
178}
179
180macro_rules! parallel_range_impl {
181 ( $t:ty ) => {
182 impl RangeInteger for $t {
183 private_impl! {}
184
185 fn drive_unindexed<C>(iter: Iter<$t>, consumer: C) -> C::Result
186 where
187 C: UnindexedConsumer<$t>,
188 {
189 convert!(iter.drive_unindexed(consumer))
190 }
191
192 fn opt_len(iter: &Iter<$t>) -> Option<usize> {
193 convert!(iter.opt_len())
194 }
195 }
196 };
197}
198
199macro_rules! indexed_range_impl {
200 ( $t:ty ) => {
201 parallel_range_impl! { $t }
202
203 impl IndexedRangeInteger for $t {
204 private_impl! {}
205
206 fn drive<C>(iter: Iter<$t>, consumer: C) -> C::Result
207 where
208 C: Consumer<$t>,
209 {
210 convert!(iter.drive(consumer))
211 }
212
213 fn len(iter: &Iter<$t>) -> usize {
214 iter.range.len()
215 }
216
217 fn with_producer<CB>(iter: Iter<$t>, callback: CB) -> CB::Output
218 where
219 CB: ProducerCallback<$t>,
220 {
221 convert!(iter.with_producer(callback))
222 }
223 }
224 };
225}
226
227indexed_range_impl! {u8}
229indexed_range_impl! {u16}
230indexed_range_impl! {i8}
231indexed_range_impl! {i16}
232
233parallel_range_impl! {usize}
235parallel_range_impl! {isize}
236parallel_range_impl! {u32}
237parallel_range_impl! {i32}
238parallel_range_impl! {u64}
239parallel_range_impl! {i64}
240parallel_range_impl! {u128}
241parallel_range_impl! {i128}
242
243macro_rules! convert_char {
245 ( $self:ident . $method:ident ( $( $arg:expr ),* ) ) => {
246 if let Some((start, end)) = $self.bounds() {
247 let start = start as u32;
248 let end = end as u32;
249 if start < 0xD800 && 0xE000 <= end {
250 (start..0xD800)
252 .into_par_iter()
253 .chain(0xE000..end + 1) .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })
255 .$method($( $arg ),*)
256 } else {
257 (start..end + 1) .into_par_iter()
260 .map(|codepoint| unsafe { char::from_u32_unchecked(codepoint) })
261 .$method($( $arg ),*)
262 }
263 } else {
264 empty::<char>().$method($( $arg ),*)
265 }
266 };
267}
268
269impl ParallelIterator for Iter<char> {
270 type Item = char;
271
272 fn drive_unindexed<C>(self, consumer: C) -> C::Result
273 where
274 C: UnindexedConsumer<Self::Item>,
275 {
276 convert_char!(self.drive(consumer))
277 }
278
279 fn opt_len(&self) -> Option<usize> {
280 Some(self.len())
281 }
282}
283
284impl IndexedParallelIterator for Iter<char> {
286 fn drive<C>(self, consumer: C) -> C::Result
288 where
289 C: Consumer<Self::Item>,
290 {
291 convert_char!(self.drive(consumer))
292 }
293
294 fn len(&self) -> usize {
295 if let Some((start, end)) = self.bounds() {
296 let start = start as u32;
298 let end = end as u32;
299 let mut count = end - start;
300 if start < 0xd800 && 0xe000 <= end {
301 count -= 0x800
302 }
303 (count + 1) as usize } else {
305 0
306 }
307 }
308
309 fn with_producer<CB>(self, callback: CB) -> CB::Output
310 where
311 CB: ProducerCallback<Self::Item>,
312 {
313 convert_char!(self.with_producer(callback))
314 }
315}
316
317#[test]
318#[cfg(target_pointer_width = "64")]
319fn test_u32_opt_len() {
320 assert_eq!(Some(101), (0..=100u32).into_par_iter().opt_len());
321 assert_eq!(
322 Some(u32::MAX as usize),
323 (0..=u32::MAX - 1).into_par_iter().opt_len()
324 );
325 assert_eq!(
326 Some(u32::MAX as usize + 1),
327 (0..=u32::MAX).into_par_iter().opt_len()
328 );
329}
330
331#[test]
332fn test_u64_opt_len() {
333 assert_eq!(Some(101), (0..=100u64).into_par_iter().opt_len());
334 assert_eq!(
335 Some(usize::MAX),
336 (0..=usize::MAX as u64 - 1).into_par_iter().opt_len()
337 );
338 assert_eq!(None, (0..=usize::MAX as u64).into_par_iter().opt_len());
339 assert_eq!(None, (0..=u64::MAX).into_par_iter().opt_len());
340}
341
342#[test]
343fn test_u128_opt_len() {
344 assert_eq!(Some(101), (0..=100u128).into_par_iter().opt_len());
345 assert_eq!(
346 Some(usize::MAX),
347 (0..=usize::MAX as u128 - 1).into_par_iter().opt_len()
348 );
349 assert_eq!(None, (0..=usize::MAX as u128).into_par_iter().opt_len());
350 assert_eq!(None, (0..=u128::MAX).into_par_iter().opt_len());
351}
352
353#[test]
369fn test_issue_833() {
370 fn is_even(n: i64) -> bool {
371 n % 2 == 0
372 }
373
374 let v: Vec<_> = (1..=100).into_par_iter().filter(|&x| is_even(x)).collect();
376 assert!(v.into_iter().eq((2..=100).step_by(2)));
377
378 let pos = (0..=100).into_par_iter().position_any(|x| x == 50i16);
380 assert_eq!(pos, Some(50usize));
381
382 assert!((0..=100)
383 .into_par_iter()
384 .zip(0..=100)
385 .all(|(a, b)| i16::eq(&a, &b)));
386}