//! Parallel iterator types for [`IndexMap`] with [`rayon`][::rayon]. //! //! You will rarely need to interact with this module directly unless you need to name one of the //! iterator types. use super::collect; use rayon::iter::plumbing::{Consumer, ProducerCallback, UnindexedConsumer}; use rayon::prelude::*; use crate::vec::Vec; use alloc::boxed::Box; use core::cmp::Ordering; use core::fmt; use core::hash::{BuildHasher, Hash}; use core::ops::RangeBounds; use crate::map::Slice; use crate::Bucket; use crate::Entries; use crate::IndexMap; impl IntoParallelIterator for IndexMap where K: Send, V: Send, { type Item = (K, V); type Iter = IntoParIter; fn into_par_iter(self) -> Self::Iter { IntoParIter { entries: self.into_entries(), } } } impl IntoParallelIterator for Box> where K: Send, V: Send, { type Item = (K, V); type Iter = IntoParIter; fn into_par_iter(self) -> Self::Iter { IntoParIter { entries: self.into_entries(), } } } /// A parallel owning iterator over the entries of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::into_par_iter`] method /// (provided by rayon's [`IntoParallelIterator`] trait). See its documentation for more. pub struct IntoParIter { entries: Vec>, } impl fmt::Debug for IntoParIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::refs); f.debug_list().entries(iter).finish() } } impl ParallelIterator for IntoParIter { type Item = (K, V); parallel_iterator_methods!(Bucket::key_value); } impl IndexedParallelIterator for IntoParIter { indexed_parallel_iterator_methods!(Bucket::key_value); } impl<'a, K, V, S> IntoParallelIterator for &'a IndexMap where K: Sync, V: Sync, { type Item = (&'a K, &'a V); type Iter = ParIter<'a, K, V>; fn into_par_iter(self) -> Self::Iter { ParIter { entries: self.as_entries(), } } } impl<'a, K, V> IntoParallelIterator for &'a Slice where K: Sync, V: Sync, { type Item = (&'a K, &'a V); type Iter = ParIter<'a, K, V>; fn into_par_iter(self) -> Self::Iter { ParIter { entries: &self.entries, } } } /// A parallel iterator over the entries of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_iter`] method /// (provided by rayon's [`IntoParallelRefIterator`] trait). See its documentation for more. /// /// [`IndexMap::par_iter`]: ../struct.IndexMap.html#method.par_iter pub struct ParIter<'a, K, V> { entries: &'a [Bucket], } impl Clone for ParIter<'_, K, V> { fn clone(&self) -> Self { ParIter { ..*self } } } impl fmt::Debug for ParIter<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::refs); f.debug_list().entries(iter).finish() } } impl<'a, K: Sync, V: Sync> ParallelIterator for ParIter<'a, K, V> { type Item = (&'a K, &'a V); parallel_iterator_methods!(Bucket::refs); } impl IndexedParallelIterator for ParIter<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::refs); } impl<'a, K, V, S> IntoParallelIterator for &'a mut IndexMap where K: Sync + Send, V: Send, { type Item = (&'a K, &'a mut V); type Iter = ParIterMut<'a, K, V>; fn into_par_iter(self) -> Self::Iter { ParIterMut { entries: self.as_entries_mut(), } } } impl<'a, K, V> IntoParallelIterator for &'a mut Slice where K: Sync + Send, V: Send, { type Item = (&'a K, &'a mut V); type Iter = ParIterMut<'a, K, V>; fn into_par_iter(self) -> Self::Iter { ParIterMut { entries: &mut self.entries, } } } /// A parallel mutable iterator over the entries of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_iter_mut`] method /// (provided by rayon's [`IntoParallelRefMutIterator`] trait). See its documentation for more. /// /// [`IndexMap::par_iter_mut`]: ../struct.IndexMap.html#method.par_iter_mut pub struct ParIterMut<'a, K, V> { entries: &'a mut [Bucket], } impl fmt::Debug for ParIterMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::refs); f.debug_list().entries(iter).finish() } } impl<'a, K: Sync + Send, V: Send> ParallelIterator for ParIterMut<'a, K, V> { type Item = (&'a K, &'a mut V); parallel_iterator_methods!(Bucket::ref_mut); } impl IndexedParallelIterator for ParIterMut<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::ref_mut); } impl<'a, K, V, S> ParallelDrainRange for &'a mut IndexMap where K: Send, V: Send, { type Item = (K, V); type Iter = ParDrain<'a, K, V>; fn par_drain>(self, range: R) -> Self::Iter { ParDrain { entries: self.core.par_drain(range), } } } /// A parallel draining iterator over the entries of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_drain`] method /// (provided by rayon's [`ParallelDrainRange`] trait). See its documentation for more. /// /// [`IndexMap::par_drain`]: ../struct.IndexMap.html#method.par_drain pub struct ParDrain<'a, K: Send, V: Send> { entries: rayon::vec::Drain<'a, Bucket>, } impl ParallelIterator for ParDrain<'_, K, V> { type Item = (K, V); parallel_iterator_methods!(Bucket::key_value); } impl IndexedParallelIterator for ParDrain<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::key_value); } /// Parallel iterator methods and other parallel methods. /// /// The following methods **require crate feature `"rayon"`**. /// /// See also the `IntoParallelIterator` implementations. impl IndexMap where K: Sync, V: Sync, { /// Return a parallel iterator over the keys of the map. /// /// While parallel iterators can process items in any order, their relative order /// in the map is still preserved for operations like `reduce` and `collect`. pub fn par_keys(&self) -> ParKeys<'_, K, V> { ParKeys { entries: self.as_entries(), } } /// Return a parallel iterator over the values of the map. /// /// While parallel iterators can process items in any order, their relative order /// in the map is still preserved for operations like `reduce` and `collect`. pub fn par_values(&self) -> ParValues<'_, K, V> { ParValues { entries: self.as_entries(), } } } /// Parallel iterator methods and other parallel methods. /// /// The following methods **require crate feature `"rayon"`**. /// /// See also the `IntoParallelIterator` implementations. impl Slice where K: Sync, V: Sync, { /// Return a parallel iterator over the keys of the map slice. /// /// While parallel iterators can process items in any order, their relative order /// in the slice is still preserved for operations like `reduce` and `collect`. pub fn par_keys(&self) -> ParKeys<'_, K, V> { ParKeys { entries: &self.entries, } } /// Return a parallel iterator over the values of the map slice. /// /// While parallel iterators can process items in any order, their relative order /// in the slice is still preserved for operations like `reduce` and `collect`. pub fn par_values(&self) -> ParValues<'_, K, V> { ParValues { entries: &self.entries, } } } impl IndexMap where K: Hash + Eq + Sync, V: Sync, S: BuildHasher, { /// Returns `true` if `self` contains all of the same key-value pairs as `other`, /// regardless of each map's indexed order, determined in parallel. pub fn par_eq(&self, other: &IndexMap) -> bool where V: PartialEq, V2: Sync, S2: BuildHasher + Sync, { self.len() == other.len() && self .par_iter() .all(move |(key, value)| other.get(key).map_or(false, |v| *value == *v)) } } /// A parallel iterator over the keys of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_keys`] method. /// See its documentation for more. pub struct ParKeys<'a, K, V> { entries: &'a [Bucket], } impl Clone for ParKeys<'_, K, V> { fn clone(&self) -> Self { ParKeys { ..*self } } } impl fmt::Debug for ParKeys<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::key_ref); f.debug_list().entries(iter).finish() } } impl<'a, K: Sync, V: Sync> ParallelIterator for ParKeys<'a, K, V> { type Item = &'a K; parallel_iterator_methods!(Bucket::key_ref); } impl IndexedParallelIterator for ParKeys<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::key_ref); } /// A parallel iterator over the values of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_values`] method. /// See its documentation for more. pub struct ParValues<'a, K, V> { entries: &'a [Bucket], } impl Clone for ParValues<'_, K, V> { fn clone(&self) -> Self { ParValues { ..*self } } } impl fmt::Debug for ParValues<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::value_ref); f.debug_list().entries(iter).finish() } } impl<'a, K: Sync, V: Sync> ParallelIterator for ParValues<'a, K, V> { type Item = &'a V; parallel_iterator_methods!(Bucket::value_ref); } impl IndexedParallelIterator for ParValues<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::value_ref); } impl IndexMap where K: Send, V: Send, { /// Return a parallel iterator over mutable references to the values of the map /// /// While parallel iterators can process items in any order, their relative order /// in the map is still preserved for operations like `reduce` and `collect`. pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> { ParValuesMut { entries: self.as_entries_mut(), } } } impl Slice where K: Send, V: Send, { /// Return a parallel iterator over mutable references to the the values of the map slice. /// /// While parallel iterators can process items in any order, their relative order /// in the slice is still preserved for operations like `reduce` and `collect`. pub fn par_values_mut(&mut self) -> ParValuesMut<'_, K, V> { ParValuesMut { entries: &mut self.entries, } } } impl IndexMap where K: Send, V: Send, { /// Sort the map’s key-value pairs in parallel, by the default ordering of the keys. pub fn par_sort_keys(&mut self) where K: Ord, { self.with_entries(|entries| { entries.par_sort_by(|a, b| K::cmp(&a.key, &b.key)); }); } /// Sort the map’s key-value pairs in place and in parallel, using the comparison /// function `cmp`. /// /// The comparison function receives two key and value pairs to compare (you /// can sort by keys or values or their combination as needed). pub fn par_sort_by(&mut self, cmp: F) where F: Fn(&K, &V, &K, &V) -> Ordering + Sync, { self.with_entries(|entries| { entries.par_sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); }); } /// Sort the key-value pairs of the map in parallel and return a by-value parallel /// iterator of the key-value pairs with the result. pub fn par_sorted_by(self, cmp: F) -> IntoParIter where F: Fn(&K, &V, &K, &V) -> Ordering + Sync, { let mut entries = self.into_entries(); entries.par_sort_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); IntoParIter { entries } } /// Sort the map's key-value pairs in parallel, by the default ordering of the keys. pub fn par_sort_unstable_keys(&mut self) where K: Ord, { self.with_entries(|entries| { entries.par_sort_unstable_by(|a, b| K::cmp(&a.key, &b.key)); }); } /// Sort the map's key-value pairs in place and in parallel, using the comparison /// function `cmp`. /// /// The comparison function receives two key and value pairs to compare (you /// can sort by keys or values or their combination as needed). pub fn par_sort_unstable_by(&mut self, cmp: F) where F: Fn(&K, &V, &K, &V) -> Ordering + Sync, { self.with_entries(|entries| { entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); }); } /// Sort the key-value pairs of the map in parallel and return a by-value parallel /// iterator of the key-value pairs with the result. pub fn par_sorted_unstable_by(self, cmp: F) -> IntoParIter where F: Fn(&K, &V, &K, &V) -> Ordering + Sync, { let mut entries = self.into_entries(); entries.par_sort_unstable_by(move |a, b| cmp(&a.key, &a.value, &b.key, &b.value)); IntoParIter { entries } } /// Sort the map’s key-value pairs in place and in parallel, using a sort-key extraction /// function. pub fn par_sort_by_cached_key(&mut self, sort_key: F) where T: Ord + Send, F: Fn(&K, &V) -> T + Sync, { self.with_entries(move |entries| { entries.par_sort_by_cached_key(move |a| sort_key(&a.key, &a.value)); }); } } /// A parallel mutable iterator over the values of an [`IndexMap`]. /// /// This `struct` is created by the [`IndexMap::par_values_mut`] method. /// See its documentation for more. pub struct ParValuesMut<'a, K, V> { entries: &'a mut [Bucket], } impl fmt::Debug for ParValuesMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let iter = self.entries.iter().map(Bucket::value_ref); f.debug_list().entries(iter).finish() } } impl<'a, K: Send, V: Send> ParallelIterator for ParValuesMut<'a, K, V> { type Item = &'a mut V; parallel_iterator_methods!(Bucket::value_mut); } impl IndexedParallelIterator for ParValuesMut<'_, K, V> { indexed_parallel_iterator_methods!(Bucket::value_mut); } impl FromParallelIterator<(K, V)> for IndexMap where K: Eq + Hash + Send, V: Send, S: BuildHasher + Default + Send, { fn from_par_iter(iter: I) -> Self where I: IntoParallelIterator, { let list = collect(iter); let len = list.iter().map(Vec::len).sum(); let mut map = Self::with_capacity_and_hasher(len, S::default()); for vec in list { map.extend(vec); } map } } impl ParallelExtend<(K, V)> for IndexMap where K: Eq + Hash + Send, V: Send, S: BuildHasher + Send, { fn par_extend(&mut self, iter: I) where I: IntoParallelIterator, { for vec in collect(iter) { self.extend(vec); } } } impl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for IndexMap where K: Copy + Eq + Hash + Send + Sync, V: Copy + Send + Sync, S: BuildHasher + Send, { fn par_extend(&mut self, iter: I) where I: IntoParallelIterator, { for vec in collect(iter) { self.extend(vec); } } } #[cfg(test)] mod tests { use super::*; use std::string::String; #[test] fn insert_order() { let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; let mut map = IndexMap::new(); for &elt in &insert { map.insert(elt, ()); } assert_eq!(map.par_keys().count(), map.len()); assert_eq!(map.par_keys().count(), insert.len()); insert.par_iter().zip(map.par_keys()).for_each(|(a, b)| { assert_eq!(a, b); }); (0..insert.len()) .into_par_iter() .zip(map.par_keys()) .for_each(|(i, k)| { assert_eq!(map.get_index(i).unwrap().0, k); }); } #[test] fn partial_eq_and_eq() { let mut map_a = IndexMap::new(); map_a.insert(1, "1"); map_a.insert(2, "2"); let mut map_b = map_a.clone(); assert!(map_a.par_eq(&map_b)); map_b.swap_remove(&1); assert!(!map_a.par_eq(&map_b)); map_b.insert(3, "3"); assert!(!map_a.par_eq(&map_b)); let map_c: IndexMap<_, String> = map_b.into_par_iter().map(|(k, v)| (k, v.into())).collect(); assert!(!map_a.par_eq(&map_c)); assert!(!map_c.par_eq(&map_a)); } #[test] fn extend() { let mut map = IndexMap::new(); map.par_extend(vec![(&1, &2), (&3, &4)]); map.par_extend(vec![(5, 6)]); assert_eq!( map.into_par_iter().collect::>(), vec![(1, 2), (3, 4), (5, 6)] ); } #[test] fn keys() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: IndexMap<_, _> = vec.into_par_iter().collect(); let keys: Vec<_> = map.par_keys().copied().collect(); assert_eq!(keys.len(), 3); assert!(keys.contains(&1)); assert!(keys.contains(&2)); assert!(keys.contains(&3)); } #[test] fn values() { let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; let map: IndexMap<_, _> = vec.into_par_iter().collect(); let values: Vec<_> = map.par_values().copied().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&'a')); assert!(values.contains(&'b')); assert!(values.contains(&'c')); } #[test] fn values_mut() { let vec = vec![(1, 1), (2, 2), (3, 3)]; let mut map: IndexMap<_, _> = vec.into_par_iter().collect(); map.par_values_mut().for_each(|value| *value *= 2); let values: Vec<_> = map.par_values().copied().collect(); assert_eq!(values.len(), 3); assert!(values.contains(&2)); assert!(values.contains(&4)); assert!(values.contains(&6)); } }