1use super::noop::NoopConsumer;
2use super::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator};
3
4use std::borrow::Cow;
5use std::collections::LinkedList;
6use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
7use std::collections::{BinaryHeap, VecDeque};
8use std::ffi::{OsStr, OsString};
9use std::hash::{BuildHasher, Hash};
10use std::rc::Rc;
11use std::sync::Arc;
12
13/// Creates an empty default collection and extends it.
14fn collect_extended<C, I>(par_iter: I) -> C
15where
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.
25impl<T> FromParallelIterator<T> for Vec<T>
26where
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.
38impl<T> FromParallelIterator<T> for Box<[T]>
39where
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.
51impl<T> FromParallelIterator<T> for Rc<[T]>
52where
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.
64impl<T> FromParallelIterator<T> for Arc<[T]>
65where
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.
77impl<T> FromParallelIterator<T> for VecDeque<T>
78where
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.
91impl<T> FromParallelIterator<T> for BinaryHeap<T>
92where
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.
105impl<T> FromParallelIterator<T> for LinkedList<T>
106where
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.
121impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>
122where
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.
139impl<K, V> FromParallelIterator<(K, V)> for BTreeMap<K, V>
140where
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.
153impl<V, S> FromParallelIterator<V> for HashSet<V, S>
154where
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.
167impl<V> FromParallelIterator<V> for BTreeSet<V>
168where
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.
180impl 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.
190impl<'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.
200impl<'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.
210impl 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.
220impl 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.
230impl<'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.
240impl<'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.
250impl 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.
260impl<'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.
274impl<'a, C: ?Sized, T> FromParallelIterator<T> for Cow<'a, C>
275where
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/// ```
303impl 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