use super::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::hash::{BuildHasher, Hash};
use std::collections::LinkedList;
use std::collections::{BinaryHeap, VecDeque};
fn combine<I, START, COLL>(par_iter: I, make_start: START) -> COLL
where I: IntoParallelIterator,
START: FnOnce(&LinkedList<Vec<I::Item>>) -> COLL,
COLL: Extend<I::Item>
{
let list = par_iter.into_par_iter()
.fold(Vec::new, |mut vec, elem| {
vec.push(elem);
vec
})
.collect();
let start = make_start(&list);
list.into_iter().fold(start, |mut coll, vec| {
coll.extend(vec);
coll
})
}
fn combined_len<T>(list: &LinkedList<Vec<T>>) -> usize {
list.iter().map(Vec::len).sum()
}
impl<T> FromParallelIterator<T> for VecDeque<T>
where T: Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = T>
{
Vec::from_par_iter(par_iter).into()
}
}
impl<T> FromParallelIterator<T> for BinaryHeap<T>
where T: Ord + Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = T>
{
Vec::from_par_iter(par_iter).into()
}
}
impl<T> FromParallelIterator<T> for LinkedList<T>
where T: Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = T>
{
par_iter.into_par_iter()
.map(|elem| {
let mut list = LinkedList::new();
list.push_back(elem);
list
})
.reduce_with(|mut list1, mut list2| {
list1.append(&mut list2);
list1
})
.unwrap_or_else(LinkedList::new)
}
}
impl<K, V, S> FromParallelIterator<(K, V)> for HashMap<K, V, S>
where K: Eq + Hash + Send,
V: Send,
S: BuildHasher + Default + Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = (K, V)>
{
combine(par_iter, |list| {
let len = combined_len(list);
HashMap::with_capacity_and_hasher(len, Default::default())
})
}
}
impl<K, V> FromParallelIterator<(K, V)> for BTreeMap<K, V>
where K: Ord + Send,
V: Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = (K, V)>
{
combine(par_iter, |_| BTreeMap::new())
}
}
impl<V, S> FromParallelIterator<V> for HashSet<V, S>
where V: Eq + Hash + Send,
S: BuildHasher + Default + Send
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = V>
{
combine(par_iter, |list| {
let len = combined_len(list);
HashSet::with_capacity_and_hasher(len, Default::default())
})
}
}
impl<V> FromParallelIterator<V> for BTreeSet<V>
where V: Send + Ord
{
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = V>
{
combine(par_iter, |_| BTreeSet::new())
}
}
impl FromParallelIterator<char> for String {
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = char>
{
let list: LinkedList<_> = par_iter.into_par_iter()
.fold(String::new, |mut string, ch| {
string.push(ch);
string
})
.collect();
let len = list.iter().map(String::len).sum();
let start = String::with_capacity(len);
list.into_iter().fold(start, |mut string, sub| {
string.push_str(&sub);
string
})
}
}
impl<'a> FromParallelIterator<&'a str> for String {
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = &'a str>
{
combine(par_iter, |list| {
let len = list.iter()
.map(|vec| -> usize {
vec.iter()
.cloned()
.map(str::len)
.sum()
})
.sum();
String::with_capacity(len)
})
}
}
impl FromParallelIterator<String> for String {
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = String>
{
combine(par_iter, |list| {
let len = list.iter().map(|vec| -> usize { vec.iter().map(String::len).sum() }).sum();
String::with_capacity(len)
})
}
}