use rayon::prelude::*; #[cfg(not(has_std))] use alloc::collections::LinkedList; #[cfg(has_std)] use std::collections::LinkedList; use crate::vec::Vec; // generate `ParallelIterator` methods by just forwarding to the underlying // self.entries and mapping its elements. macro_rules! parallel_iterator_methods { // $map_elt is the mapping function from the underlying iterator's element ($map_elt:expr) => { fn drive_unindexed(self, consumer: C) -> C::Result where C: UnindexedConsumer, { self.entries .into_par_iter() .map($map_elt) .drive_unindexed(consumer) } // NB: This allows indexed collection, e.g. directly into a `Vec`, but the // underlying iterator must really be indexed. We should remove this if we // start having tombstones that must be filtered out. fn opt_len(&self) -> Option { Some(self.entries.len()) } }; } // generate `IndexedParallelIterator` methods by just forwarding to the underlying // self.entries and mapping its elements. macro_rules! indexed_parallel_iterator_methods { // $map_elt is the mapping function from the underlying iterator's element ($map_elt:expr) => { fn drive(self, consumer: C) -> C::Result where C: Consumer, { self.entries.into_par_iter().map($map_elt).drive(consumer) } fn len(&self) -> usize { self.entries.len() } fn with_producer(self, callback: CB) -> CB::Output where CB: ProducerCallback, { self.entries .into_par_iter() .map($map_elt) .with_producer(callback) } }; } pub mod map; pub mod set; // This form of intermediate collection is also how Rayon collects `HashMap`. // Note that the order will also be preserved! fn collect(iter: I) -> LinkedList> { iter.into_par_iter() .fold(Vec::new, |mut vec, elem| { vec.push(elem); vec }) .map(|vec| { let mut list = LinkedList::new(); list.push_back(vec); list }) .reduce(LinkedList::new, |mut list1, mut list2| { list1.append(&mut list2); list1 }) }