use crate::setref::multiple::RefMulti; use crate::DashSet; use core::hash::{BuildHasher, Hash}; use rayon::iter::plumbing::UnindexedConsumer; use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelExtend, ParallelIterator}; use std::collections::hash_map::RandomState; impl ParallelExtend for DashSet where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + BuildHasher, { fn par_extend(&mut self, par_iter: I) where I: IntoParallelIterator, { (&*self).par_extend(par_iter); } } // Since we don't actually need mutability, we can implement this on a // reference, similar to `io::Write for &File`. impl ParallelExtend for &'_ DashSet where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + BuildHasher, { fn par_extend(&mut self, par_iter: I) where I: IntoParallelIterator, { let &mut set = self; par_iter.into_par_iter().for_each(move |key| { set.insert(key); }); } } impl FromParallelIterator for DashSet where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + Default + BuildHasher, { fn from_par_iter(par_iter: I) -> Self where I: IntoParallelIterator, { let set = Self::default(); (&set).par_extend(par_iter); set } } impl IntoParallelIterator for DashSet where K: Send + Eq + Hash, S: Send + Clone + BuildHasher, { type Iter = OwningIter; type Item = K; fn into_par_iter(self) -> Self::Iter { OwningIter { inner: self.inner.into_par_iter(), } } } pub struct OwningIter { inner: super::map::OwningIter, } impl ParallelIterator for OwningIter where K: Send + Eq + Hash, S: Send + Clone + BuildHasher, { type Item = K; fn drive_unindexed(self, consumer: C) -> C::Result where C: UnindexedConsumer, { self.inner.map(|(k, _)| k).drive_unindexed(consumer) } } // This impl also enables `IntoParallelRefIterator::par_iter` impl<'a, K, S> IntoParallelIterator for &'a DashSet where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + BuildHasher, { type Iter = Iter<'a, K, S>; type Item = RefMulti<'a, K, S>; fn into_par_iter(self) -> Self::Iter { Iter { inner: (&self.inner).into_par_iter(), } } } pub struct Iter<'a, K, S = RandomState> { inner: super::map::Iter<'a, K, (), S>, } impl<'a, K, S> ParallelIterator for Iter<'a, K, S> where K: Send + Sync + Eq + Hash, S: Send + Sync + Clone + BuildHasher, { type Item = RefMulti<'a, K, S>; fn drive_unindexed(self, consumer: C) -> C::Result where C: UnindexedConsumer, { self.inner.map(RefMulti::new).drive_unindexed(consumer) } }