1 use super::noop::NoopConsumer;
2 use super::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
3 
4 use std::borrow::Cow;
5 use std::collections::LinkedList;
6 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7 use std::collections::{BinaryHeap, VecDeque};
8 use std::hash::{BuildHasher, Hash};
9 
10 /// Creates an empty default collection and extends it.
collect_extended<C, I>(par_iter: I) -> C where I: IntoParallelIterator, C: ParallelExtend<I::Item> + Default,11 fn collect_extended<C, I>(par_iter: I) -> C
12 where
13     I: IntoParallelIterator,
14     C: ParallelExtend<I::Item> + Default,
15 {
16     let mut collection = C::default();
17     collection.par_extend(par_iter);
18     collection
19 }
20 
21 /// Collects items from a parallel iterator into a vector.
22 impl<T> FromParallelIterator<T> for Vec<T>
23 where
24     T: Send,
25 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = T>,26     fn from_par_iter<I>(par_iter: I) -> Self
27     where
28         I: IntoParallelIterator<Item = T>,
29     {
30         collect_extended(par_iter)
31     }
32 }
33 
34 /// Collects items from a parallel iterator into a vecdeque.
35 impl<T> FromParallelIterator<T> for VecDeque<T>
36 where
37     T: Send,
38 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = T>,39     fn from_par_iter<I>(par_iter: I) -> Self
40     where
41         I: IntoParallelIterator<Item = T>,
42     {
43         Vec::from_par_iter(par_iter).into()
44     }
45 }
46 
47 /// Collects items from a parallel iterator into a binaryheap.
48 /// The heap-ordering is calculated serially after all items are collected.
49 impl<T> FromParallelIterator<T> for BinaryHeap<T>
50 where
51     T: Ord + Send,
52 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = T>,53     fn from_par_iter<I>(par_iter: I) -> Self
54     where
55         I: IntoParallelIterator<Item = T>,
56     {
57         Vec::from_par_iter(par_iter).into()
58     }
59 }
60 
61 /// Collects items from a parallel iterator into a freshly allocated
62 /// linked list.
63 impl<T> FromParallelIterator<T> for LinkedList<T>
64 where
65     T: Send,
66 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = T>,67     fn from_par_iter<I>(par_iter: I) -> Self
68     where
69         I: IntoParallelIterator<Item = T>,
70     {
71         collect_extended(par_iter)
72     }
73 }
74 
75 /// Collects (key, value) pairs from a parallel iterator into a
76 /// hashmap. If multiple pairs correspond to the same key, then the
77 /// ones produced earlier in the parallel iterator will be
78 /// overwritten, just as with a sequential iterator.
79 impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>
80 where
81     K: Eq + Hash + Send,
82     V: Send,
83     S: BuildHasher + Default + Send,
84 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = (K, V)>,85     fn from_par_iter<I>(par_iter: I) -> Self
86     where
87         I: IntoParallelIterator<Item = (K, V)>,
88     {
89         collect_extended(par_iter)
90     }
91 }
92 
93 /// Collects (key, value) pairs from a parallel iterator into a
94 /// btreemap. If multiple pairs correspond to the same key, then the
95 /// ones produced earlier in the parallel iterator will be
96 /// overwritten, just as with a sequential iterator.
97 impl<K, V> FromParallelIterator<(K, V)> for BTreeMap<K, V>
98 where
99     K: Ord + Send,
100     V: Send,
101 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = (K, V)>,102     fn from_par_iter<I>(par_iter: I) -> Self
103     where
104         I: IntoParallelIterator<Item = (K, V)>,
105     {
106         collect_extended(par_iter)
107     }
108 }
109 
110 /// Collects values from a parallel iterator into a hashset.
111 impl<V, S> FromParallelIterator<V> for HashSet<V, S>
112 where
113     V: Eq + Hash + Send,
114     S: BuildHasher + Default + Send,
115 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = V>,116     fn from_par_iter<I>(par_iter: I) -> Self
117     where
118         I: IntoParallelIterator<Item = V>,
119     {
120         collect_extended(par_iter)
121     }
122 }
123 
124 /// Collects values from a parallel iterator into a btreeset.
125 impl<V> FromParallelIterator<V> for BTreeSet<V>
126 where
127     V: Send + Ord,
128 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = V>,129     fn from_par_iter<I>(par_iter: I) -> Self
130     where
131         I: IntoParallelIterator<Item = V>,
132     {
133         collect_extended(par_iter)
134     }
135 }
136 
137 /// Collects characters from a parallel iterator into a string.
138 impl FromParallelIterator<char> for String {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = char>,139     fn from_par_iter<I>(par_iter: I) -> Self
140     where
141         I: IntoParallelIterator<Item = char>,
142     {
143         collect_extended(par_iter)
144     }
145 }
146 
147 /// Collects characters from a parallel iterator into a string.
148 impl<'a> FromParallelIterator<&'a char> for String {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = &'a char>,149     fn from_par_iter<I>(par_iter: I) -> Self
150     where
151         I: IntoParallelIterator<Item = &'a char>,
152     {
153         collect_extended(par_iter)
154     }
155 }
156 
157 /// Collects string slices from a parallel iterator into a string.
158 impl<'a> FromParallelIterator<&'a str> for String {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = &'a str>,159     fn from_par_iter<I>(par_iter: I) -> Self
160     where
161         I: IntoParallelIterator<Item = &'a str>,
162     {
163         collect_extended(par_iter)
164     }
165 }
166 
167 /// Collects strings from a parallel iterator into one large string.
168 impl FromParallelIterator<String> for String {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = String>,169     fn from_par_iter<I>(par_iter: I) -> Self
170     where
171         I: IntoParallelIterator<Item = String>,
172     {
173         collect_extended(par_iter)
174     }
175 }
176 
177 /// Collects string slices from a parallel iterator into a string.
178 impl<'a> FromParallelIterator<Cow<'a, str>> for String {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = Cow<'a, str>>,179     fn from_par_iter<I>(par_iter: I) -> Self
180     where
181         I: IntoParallelIterator<Item = Cow<'a, str>>,
182     {
183         collect_extended(par_iter)
184     }
185 }
186 
187 /// Collects an arbitrary `Cow` collection.
188 ///
189 /// Note, the standard library only has `FromIterator` for `Cow<'a, str>` and
190 /// `Cow<'a, [T]>`, because no one thought to add a blanket implementation
191 /// before it was stabilized.
192 impl<'a, C: ?Sized, T> FromParallelIterator<T> for Cow<'a, C>
193 where
194     C: ToOwned,
195     C::Owned: FromParallelIterator<T>,
196     T: Send,
197 {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = T>,198     fn from_par_iter<I>(par_iter: I) -> Self
199     where
200         I: IntoParallelIterator<Item = T>,
201     {
202         Cow::Owned(C::Owned::from_par_iter(par_iter))
203     }
204 }
205 
206 /// Collapses all unit items from a parallel iterator into one.
207 ///
208 /// This is more useful when combined with higher-level abstractions, like
209 /// collecting to a `Result<(), E>` where you only care about errors:
210 ///
211 /// ```
212 /// use std::io::*;
213 /// use rayon::prelude::*;
214 ///
215 /// let data = vec![1, 2, 3, 4, 5];
216 /// let res: Result<()> = data.par_iter()
217 ///     .map(|x| writeln!(stdout(), "{}", x))
218 ///     .collect();
219 /// assert!(res.is_ok());
220 /// ```
221 impl FromParallelIterator<()> for () {
from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = ()>,222     fn from_par_iter<I>(par_iter: I) -> Self
223     where
224         I: IntoParallelIterator<Item = ()>,
225     {
226         par_iter.into_par_iter().drive_unindexed(NoopConsumer)
227     }
228 }
229