]>
Commit | Line | Data |
---|---|---|
2c00a5a8 XL |
1 | //! Macros for delegating newtype iterators to inner types. |
2 | ||
3 | // Note: these place `impl` bounds at the end, as token gobbling is the only way | |
4 | // I know how to consume an arbitrary list of constraints, with `$($args:tt)*`. | |
5 | ||
f035d41b | 6 | /// Creates a parallel iterator implementation which simply wraps an inner type |
2c00a5a8 XL |
7 | /// and delegates all methods inward. The actual struct must already be |
8 | /// declared with an `inner` field. | |
9 | /// | |
10 | /// The implementation of `IntoParallelIterator` should be added separately. | |
2c00a5a8 XL |
11 | macro_rules! delegate_iterator { |
12 | ($iter:ty => $item:ty , | |
13 | impl $( $args:tt )* | |
14 | ) => { | |
15 | impl $( $args )* ParallelIterator for $iter { | |
16 | type Item = $item; | |
17 | ||
18 | fn drive_unindexed<C>(self, consumer: C) -> C::Result | |
19 | where C: UnindexedConsumer<Self::Item> | |
20 | { | |
21 | self.inner.drive_unindexed(consumer) | |
22 | } | |
23 | ||
24 | fn opt_len(&self) -> Option<usize> { | |
25 | self.inner.opt_len() | |
26 | } | |
27 | } | |
28 | } | |
29 | } | |
30 | ||
f035d41b | 31 | /// Creates an indexed parallel iterator implementation which simply wraps an |
2c00a5a8 XL |
32 | /// inner type and delegates all methods inward. The actual struct must already |
33 | /// be declared with an `inner` field. | |
34 | macro_rules! delegate_indexed_iterator { | |
35 | ($iter:ty => $item:ty , | |
36 | impl $( $args:tt )* | |
37 | ) => { | |
38 | delegate_iterator!{ | |
39 | $iter => $item , | |
40 | impl $( $args )* | |
41 | } | |
42 | ||
43 | impl $( $args )* IndexedParallelIterator for $iter { | |
44 | fn drive<C>(self, consumer: C) -> C::Result | |
45 | where C: Consumer<Self::Item> | |
46 | { | |
47 | self.inner.drive(consumer) | |
48 | } | |
49 | ||
50 | fn len(&self) -> usize { | |
51 | self.inner.len() | |
52 | } | |
53 | ||
54 | fn with_producer<CB>(self, callback: CB) -> CB::Output | |
55 | where CB: ProducerCallback<Self::Item> | |
56 | { | |
57 | self.inner.with_producer(callback) | |
58 | } | |
59 | } | |
60 | } | |
61 | } | |
923072b8 FG |
62 | |
63 | #[test] | |
64 | fn unindexed_example() { | |
65 | use crate::collections::btree_map::IntoIter; | |
66 | use crate::iter::plumbing::*; | |
67 | use crate::prelude::*; | |
68 | ||
69 | use std::collections::BTreeMap; | |
70 | ||
71 | struct MyIntoIter<T: Ord + Send, U: Send> { | |
72 | inner: IntoIter<T, U>, | |
73 | } | |
74 | ||
75 | delegate_iterator! { | |
76 | MyIntoIter<T, U> => (T, U), | |
77 | impl<T: Ord + Send, U: Send> | |
78 | } | |
79 | ||
80 | let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]); | |
81 | let iter = MyIntoIter { | |
82 | inner: map.into_par_iter(), | |
83 | }; | |
84 | let vec: Vec<_> = iter.map(|(k, _)| k).collect(); | |
85 | assert_eq!(vec, &[1, 2, 3]); | |
86 | } | |
87 | ||
88 | #[test] | |
89 | fn indexed_example() { | |
90 | use crate::iter::plumbing::*; | |
91 | use crate::prelude::*; | |
92 | use crate::vec::IntoIter; | |
93 | ||
94 | struct MyIntoIter<T: Send> { | |
95 | inner: IntoIter<T>, | |
96 | } | |
97 | ||
98 | delegate_indexed_iterator! { | |
99 | MyIntoIter<T> => T, | |
100 | impl<T: Send> | |
101 | } | |
102 | ||
103 | let iter = MyIntoIter { | |
104 | inner: vec![1, 2, 3].into_par_iter(), | |
105 | }; | |
106 | let mut vec = vec![]; | |
107 | iter.collect_into_vec(&mut vec); | |
108 | assert_eq!(vec, &[1, 2, 3]); | |
109 | } |