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::ffi::{OsStr, OsString}; |
9 | use std::hash::{BuildHasher, Hash}; |
10 | use std::rc::Rc; |
11 | use std::sync::Arc; |
12 | |
13 | /// Creates an empty default collection and extends it. |
14 | fn collect_extended<C, I>(par_iter: I) -> C |
15 | where |
16 | I: IntoParallelIterator, |
17 | C: ParallelExtend<I::Item> + Default, |
18 | { |
19 | let mut collection: C = C::default(); |
20 | collection.par_extend(par_iter); |
21 | collection |
22 | } |
23 | |
24 | /// Collects items from a parallel iterator into a vector. |
25 | impl<T> FromParallelIterator<T> for Vec<T> |
26 | where |
27 | T: Send, |
28 | { |
29 | fn from_par_iter<I>(par_iter: I) -> Self |
30 | where |
31 | I: IntoParallelIterator<Item = T>, |
32 | { |
33 | collect_extended(par_iter) |
34 | } |
35 | } |
36 | |
37 | /// Collects items from a parallel iterator into a boxed slice. |
38 | impl<T> FromParallelIterator<T> for Box<[T]> |
39 | where |
40 | T: Send, |
41 | { |
42 | fn from_par_iter<I>(par_iter: I) -> Self |
43 | where |
44 | I: IntoParallelIterator<Item = T>, |
45 | { |
46 | Vec::from_par_iter(par_iter).into() |
47 | } |
48 | } |
49 | |
50 | /// Collects items from a parallel iterator into a reference-counted slice. |
51 | impl<T> FromParallelIterator<T> for Rc<[T]> |
52 | where |
53 | T: Send, |
54 | { |
55 | fn from_par_iter<I>(par_iter: I) -> Self |
56 | where |
57 | I: IntoParallelIterator<Item = T>, |
58 | { |
59 | Vec::from_par_iter(par_iter).into() |
60 | } |
61 | } |
62 | |
63 | /// Collects items from a parallel iterator into an atomically-reference-counted slice. |
64 | impl<T> FromParallelIterator<T> for Arc<[T]> |
65 | where |
66 | T: Send, |
67 | { |
68 | fn from_par_iter<I>(par_iter: I) -> Self |
69 | where |
70 | I: IntoParallelIterator<Item = T>, |
71 | { |
72 | Vec::from_par_iter(par_iter).into() |
73 | } |
74 | } |
75 | |
76 | /// Collects items from a parallel iterator into a vecdeque. |
77 | impl<T> FromParallelIterator<T> for VecDeque<T> |
78 | where |
79 | T: Send, |
80 | { |
81 | fn from_par_iter<I>(par_iter: I) -> Self |
82 | where |
83 | I: IntoParallelIterator<Item = T>, |
84 | { |
85 | Vec::from_par_iter(par_iter).into() |
86 | } |
87 | } |
88 | |
89 | /// Collects items from a parallel iterator into a binaryheap. |
90 | /// The heap-ordering is calculated serially after all items are collected. |
91 | impl<T> FromParallelIterator<T> for BinaryHeap<T> |
92 | where |
93 | T: Ord + Send, |
94 | { |
95 | fn from_par_iter<I>(par_iter: I) -> Self |
96 | where |
97 | I: IntoParallelIterator<Item = T>, |
98 | { |
99 | Vec::from_par_iter(par_iter).into() |
100 | } |
101 | } |
102 | |
103 | /// Collects items from a parallel iterator into a freshly allocated |
104 | /// linked list. |
105 | impl<T> FromParallelIterator<T> for LinkedList<T> |
106 | where |
107 | T: Send, |
108 | { |
109 | fn from_par_iter<I>(par_iter: I) -> Self |
110 | where |
111 | I: IntoParallelIterator<Item = T>, |
112 | { |
113 | collect_extended(par_iter) |
114 | } |
115 | } |
116 | |
117 | /// Collects (key, value) pairs from a parallel iterator into a |
118 | /// hashmap. If multiple pairs correspond to the same key, then the |
119 | /// ones produced earlier in the parallel iterator will be |
120 | /// overwritten, just as with a sequential iterator. |
121 | impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S> |
122 | where |
123 | K: Eq + Hash + Send, |
124 | V: Send, |
125 | S: BuildHasher + Default + Send, |
126 | { |
127 | fn from_par_iter<I>(par_iter: I) -> Self |
128 | where |
129 | I: IntoParallelIterator<Item = (K, V)>, |
130 | { |
131 | collect_extended(par_iter) |
132 | } |
133 | } |
134 | |
135 | /// Collects (key, value) pairs from a parallel iterator into a |
136 | /// btreemap. If multiple pairs correspond to the same key, then the |
137 | /// ones produced earlier in the parallel iterator will be |
138 | /// overwritten, just as with a sequential iterator. |
139 | impl<K, V> FromParallelIterator<(K, V)> for BTreeMap<K, V> |
140 | where |
141 | K: Ord + Send, |
142 | V: Send, |
143 | { |
144 | fn from_par_iter<I>(par_iter: I) -> Self |
145 | where |
146 | I: IntoParallelIterator<Item = (K, V)>, |
147 | { |
148 | collect_extended(par_iter) |
149 | } |
150 | } |
151 | |
152 | /// Collects values from a parallel iterator into a hashset. |
153 | impl<V, S> FromParallelIterator<V> for HashSet<V, S> |
154 | where |
155 | V: Eq + Hash + Send, |
156 | S: BuildHasher + Default + Send, |
157 | { |
158 | fn from_par_iter<I>(par_iter: I) -> Self |
159 | where |
160 | I: IntoParallelIterator<Item = V>, |
161 | { |
162 | collect_extended(par_iter) |
163 | } |
164 | } |
165 | |
166 | /// Collects values from a parallel iterator into a btreeset. |
167 | impl<V> FromParallelIterator<V> for BTreeSet<V> |
168 | where |
169 | V: Send + Ord, |
170 | { |
171 | fn from_par_iter<I>(par_iter: I) -> Self |
172 | where |
173 | I: IntoParallelIterator<Item = V>, |
174 | { |
175 | collect_extended(par_iter) |
176 | } |
177 | } |
178 | |
179 | /// Collects characters from a parallel iterator into a string. |
180 | impl FromParallelIterator<char> for String { |
181 | fn from_par_iter<I>(par_iter: I) -> Self |
182 | where |
183 | I: IntoParallelIterator<Item = char>, |
184 | { |
185 | collect_extended(par_iter) |
186 | } |
187 | } |
188 | |
189 | /// Collects characters from a parallel iterator into a string. |
190 | impl<'a> FromParallelIterator<&'a char> for String { |
191 | fn from_par_iter<I>(par_iter: I) -> Self |
192 | where |
193 | I: IntoParallelIterator<Item = &'a char>, |
194 | { |
195 | collect_extended(par_iter) |
196 | } |
197 | } |
198 | |
199 | /// Collects string slices from a parallel iterator into a string. |
200 | impl<'a> FromParallelIterator<&'a str> for String { |
201 | fn from_par_iter<I>(par_iter: I) -> Self |
202 | where |
203 | I: IntoParallelIterator<Item = &'a str>, |
204 | { |
205 | collect_extended(par_iter) |
206 | } |
207 | } |
208 | |
209 | /// Collects strings from a parallel iterator into one large string. |
210 | impl FromParallelIterator<String> for String { |
211 | fn from_par_iter<I>(par_iter: I) -> Self |
212 | where |
213 | I: IntoParallelIterator<Item = String>, |
214 | { |
215 | collect_extended(par_iter) |
216 | } |
217 | } |
218 | |
219 | /// Collects boxed strings from a parallel iterator into one large string. |
220 | impl FromParallelIterator<Box<str>> for String { |
221 | fn from_par_iter<I>(par_iter: I) -> Self |
222 | where |
223 | I: IntoParallelIterator<Item = Box<str>>, |
224 | { |
225 | collect_extended(par_iter) |
226 | } |
227 | } |
228 | |
229 | /// Collects string slices from a parallel iterator into a string. |
230 | impl<'a> FromParallelIterator<Cow<'a, str>> for String { |
231 | fn from_par_iter<I>(par_iter: I) -> Self |
232 | where |
233 | I: IntoParallelIterator<Item = Cow<'a, str>>, |
234 | { |
235 | collect_extended(par_iter) |
236 | } |
237 | } |
238 | |
239 | /// Collects OS-string slices from a parallel iterator into an OS-string. |
240 | impl<'a> FromParallelIterator<&'a OsStr> for OsString { |
241 | fn from_par_iter<I>(par_iter: I) -> Self |
242 | where |
243 | I: IntoParallelIterator<Item = &'a OsStr>, |
244 | { |
245 | collect_extended(par_iter) |
246 | } |
247 | } |
248 | |
249 | /// Collects OS-strings from a parallel iterator into one large OS-string. |
250 | impl FromParallelIterator<OsString> for OsString { |
251 | fn from_par_iter<I>(par_iter: I) -> Self |
252 | where |
253 | I: IntoParallelIterator<Item = OsString>, |
254 | { |
255 | collect_extended(par_iter) |
256 | } |
257 | } |
258 | |
259 | /// Collects OS-string slices from a parallel iterator into an OS-string. |
260 | impl<'a> FromParallelIterator<Cow<'a, OsStr>> for OsString { |
261 | fn from_par_iter<I>(par_iter: I) -> Self |
262 | where |
263 | I: IntoParallelIterator<Item = Cow<'a, OsStr>>, |
264 | { |
265 | collect_extended(par_iter) |
266 | } |
267 | } |
268 | |
269 | /// Collects an arbitrary `Cow` collection. |
270 | /// |
271 | /// Note, the standard library only has `FromIterator` for `Cow<'a, str>` and |
272 | /// `Cow<'a, [T]>`, because no one thought to add a blanket implementation |
273 | /// before it was stabilized. |
274 | impl<'a, C: ?Sized, T> FromParallelIterator<T> for Cow<'a, C> |
275 | where |
276 | C: ToOwned, |
277 | C::Owned: FromParallelIterator<T>, |
278 | T: Send, |
279 | { |
280 | fn from_par_iter<I>(par_iter: I) -> Self |
281 | where |
282 | I: IntoParallelIterator<Item = T>, |
283 | { |
284 | Cow::Owned(C::Owned::from_par_iter(par_iter)) |
285 | } |
286 | } |
287 | |
288 | /// Collapses all unit items from a parallel iterator into one. |
289 | /// |
290 | /// This is more useful when combined with higher-level abstractions, like |
291 | /// collecting to a `Result<(), E>` where you only care about errors: |
292 | /// |
293 | /// ``` |
294 | /// use std::io::*; |
295 | /// use rayon::prelude::*; |
296 | /// |
297 | /// let data = vec![1, 2, 3, 4, 5]; |
298 | /// let res: Result<()> = data.par_iter() |
299 | /// .map(|x| writeln!(stdout(), "{}" , x)) |
300 | /// .collect(); |
301 | /// assert!(res.is_ok()); |
302 | /// ``` |
303 | impl FromParallelIterator<()> for () { |
304 | fn from_par_iter<I>(par_iter: I) -> Self |
305 | where |
306 | I: IntoParallelIterator<Item = ()>, |
307 | { |
308 | par_iter.into_par_iter().drive_unindexed(consumer:NoopConsumer) |
309 | } |
310 | } |
311 | |