asparit 0.1.0

Async Parallel Iterators for Rust
Documentation
use std::ops::RangeBounds;

use crate::ParallelIterator;

/// `ParallelDrainFull` creates a parallel iterator that moves all items
/// from a collection while retaining the original capacity.
///
/// Types which are indexable typically implement [`ParallelDrainRange`]
/// instead, where you can drain fully with `par_drain(..)`.
///
/// [`ParallelDrainRange`]: trait.ParallelDrainRange.html
pub trait ParallelDrainFull<'a> {
    /// The draining parallel iterator type that will be created.
    type Iter: ParallelIterator<'a, Item = Self::Item>;

    /// The type of item that the parallel iterator will produce.
    /// This is usually the same as `IntoParallelIterator::Item`.
    type Item: Send + 'a;

    /// Returns a draining parallel iterator over an entire collection.
    ///
    /// When the iterator is dropped, all items are removed, even if the
    /// iterator was not fully consumed. If the iterator is leaked, for example
    /// using `std::mem::forget`, it is unspecified how many items are removed.
    ///
    /// # Examples
    ///
    /// ```
    /// use asparit::*;
    /// use std::collections::{BinaryHeap, HashSet};
    ///
    /// let squares: HashSet<i32> = (0..10).map(|x| x * x).collect();
    ///
    /// let mut heap: BinaryHeap<_> = squares.iter().copied().collect();
    /// assert_eq!(
    ///     // heaps are drained in arbitrary order
    ///     heap.par_drain()
    ///         .inspect(|x| assert!(squares.contains(x)))
    ///         .count()
    ///         .exec(),
    ///     squares.len(),
    /// );
    /// assert!(heap.is_empty());
    /// assert!(heap.capacity() >= squares.len());
    /// ```
    fn par_drain(self) -> Self::Iter;
}

/// `ParallelDrainRange` creates a parallel iterator that moves a range of items
/// from a collection while retaining the original capacity.
///
/// Types which are not indexable may implement [`ParallelDrainFull`] instead.
///
/// [`ParallelDrainFull`]: trait.ParallelDrainFull.html
pub trait ParallelDrainRange<'a, Idx = usize> {
    /// The draining parallel iterator type that will be created.
    type Iter: ParallelIterator<'a, Item = Self::Item>;

    /// The type of item that the parallel iterator will produce.
    /// This is usually the same as `IntoParallelIterator::Item`.
    type Item: Send + 'a;

    /// Returns a draining parallel iterator over a range of the collection.
    ///
    /// When the iterator is dropped, all items in the range are removed, even
    /// if the iterator was not fully consumed. If the iterator is leaked, for
    /// example using `std::mem::forget`, it is unspecified how many items are
    /// removed.
    ///
    /// # Examples
    ///
    /// ```
    /// use asparit::*;
    ///
    /// let squares: Vec<i32> = (0..10).map(|x| x * x).collect();
    ///
    /// println!("RangeFull");
    /// let mut vec = squares.clone();
    /// assert!(vec.par_drain(..).eq(squares.par_iter().copied()).exec());
    /// assert!(vec.is_empty());
    /// assert!(vec.capacity() >= squares.len());
    ///
    /// println!("RangeFrom");
    /// let mut vec = squares.clone();
    /// assert!(vec
    ///     .par_drain(5..)
    ///     .eq(squares[5..].par_iter().copied())
    ///     .exec());
    /// assert_eq!(&vec[..], &squares[..5]);
    /// assert!(vec.capacity() >= squares.len());
    ///
    /// println!("RangeTo");
    /// let mut vec = squares.clone();
    /// assert!(vec
    ///     .par_drain(..5)
    ///     .eq(squares[..5].par_iter().copied())
    ///     .exec());
    /// assert_eq!(&vec[..], &squares[5..]);
    /// assert!(vec.capacity() >= squares.len());
    ///
    /// println!("RangeToInclusive");
    /// let mut vec = squares.clone();
    /// assert!(vec
    ///     .par_drain(..=5)
    ///     .eq(squares[..=5].par_iter().copied())
    ///     .exec());
    /// assert_eq!(&vec[..], &squares[6..]);
    /// assert!(vec.capacity() >= squares.len());
    ///
    /// println!("Range");
    /// let mut vec = squares.clone();
    /// assert!(vec
    ///     .par_drain(3..7)
    ///     .eq(squares[3..7].par_iter().copied())
    ///     .exec());
    /// assert_eq!(&vec[..3], &squares[..3]);
    /// assert_eq!(&vec[3..], &squares[7..]);
    /// assert!(vec.capacity() >= squares.len());
    ///
    /// println!("RangeInclusive");
    /// let mut vec = squares.clone();
    /// assert!(vec
    ///     .par_drain(3..=7)
    ///     .eq(squares[3..=7].par_iter().copied())
    ///     .exec());
    /// assert_eq!(&vec[..3], &squares[..3]);
    /// assert_eq!(&vec[3..], &squares[8..]);
    /// assert!(vec.capacity() >= squares.len());
    /// ```
    fn par_drain<R: RangeBounds<Idx>>(self, range: R) -> Self::Iter;
}