slicetools 0.3.0

Add extra iterators to slices.
Documentation
//! This crate aims to provide various tools for slices.
//!
//! This crate use its own streaming iterator
//! due to the lack of generic associated type in the language:
//! you therefore cannot use those iterators with the `for` control flow.
//! Use the `while let` control flow, or the macro helper, as you can see below.
//!
//! # Example
//!
//! ```
//! use slicetools::*;
//!
//! let mut v = vec![1, 2, 3, 4];
//! {
//!     let mut it = v.pairs_mut();
//!     
//!     while let Some((a, b)) = it.next() {
//!         if *b > *a {
//!             *a += 1;
//!         }
//!     }
//! }
//! assert_eq!(v, &[4, 4, 4, 4]);
//! ```
//! 
//! Or, with the helper macro (do not forget to `#[macro_use]`):
//!
//! ```
//! use slicetools::*;
//! 
//! let mut v = vec![1, 2, 3, 4];
//! 
//! stream!( v.pairs_mut() => (a, b) in {
//!     if *b > *a {
//!         *a += 1;
//!     }
//! });
//! assert_eq!(v, &[4, 4, 4, 4]);
//! ```


mod streamer;
pub use streamer::StreamerMut;


mod cartesian_product_mut;
use cartesian_product_mut::CartesianProductMut;
mod pairs_mut;
use pairs_mut::PairsMut;
mod group_mut;
use group_mut::{GroupMut, GroupByMut, GroupByKeyMut};


/// Convenient helper to use easily the custom streaming iterator.
#[macro_export]
macro_rules! stream {
    { $iter:expr => $item:pat in $b:block } => {{
        let mut it = $iter;

        while let Some($item) = it.next() {
            $b
        }
    }}
}


/// A trait to extend slices and `Vec`s with streaming iterators.
pub trait SliceTools {

    /// Iterate on all the pairs (a, b) from slices A and B such as a ∈ A and b ∈ B,
    /// yielding mutables references on items.
    ///
    /// # Example
    ///
    /// ```
    /// use slicetools::*;
    ///
    /// let mut v1 = vec![100; 3];
    /// let mut v2 = vec![1, 2, 3, 4];
    /// {
    ///     let mut it = v1.cartesian_product_mut(&mut v2);
    ///     
    ///     while let Some((a, b)) = it.next() {
    ///         *a += *b;
    ///     }
    /// }
    /// assert_eq!(v1, &[110; 3]);
    /// ```
    fn cartesian_product_mut<'a, S, T: 'a, U: 'a>(&'a mut self, slice: &'a mut S) -> CartesianProductMut<'a, T, U>
        where Self: AsMut<[T]>, S: AsMut<[U]>
    {
        CartesianProductMut::new(self.as_mut(), slice.as_mut())
    }

    /// Iterate on all the possible pairs of the slice,
    /// yielding mutables references on items.
    ///
    /// # Example
    ///
    /// ```
    /// use slicetools::*;
    ///
    /// let mut v = vec![1, 2, 3, 4];
    /// {
    ///     let mut it = v.pairs_mut();
    ///     
    ///     while let Some((a, b)) = it.next() {
    ///         if *b > *a {
    ///             *a += 1;
    ///         }
    ///     }
    /// }
    /// assert_eq!(v, &[4, 4, 4, 4]);
    /// ```
    fn pairs_mut<'a, T: 'a>(&'a mut self) -> PairsMut<'a, T>
        where Self: AsMut<[T]>
    {
        PairsMut::new(self.as_mut())
    }

    /// Iterate on groups of equal items,
    /// yielding mutables references on slices.
    ///
    /// # Example
    ///
    /// ```
    /// use slicetools::*;
    ///
    /// let mut v = vec![100, 100, 100, 200, 200, 200, 200];
    /// {
    ///     let mut it = v.group_mut();
    ///     
    ///     while let Some(slice) = it.next() {
    ///         for (i, num) in slice.iter_mut().enumerate() {
    ///             *num += i;
    ///         }
    ///     }
    /// }
    /// assert_eq!(v, &[100, 101, 102, 200, 201, 202, 203]);
    /// ```
    fn group_mut<'a, T: 'a>(&'a mut self) -> GroupMut<'a, T>
        where Self: AsMut<[T]>, T: PartialEq
    {
        GroupMut::new(self.as_mut())
    }

    /// Iterate on groups of equal items,
    /// yielding mutables references on slices.
    ///
    /// # Example
    ///
    /// ```
    /// use slicetools::*;
    ///
    /// let mut v = vec![(0, 10), (0, 10), (1, 10), (1, 10), (1, 10)];
    /// {
    ///     let mut it = v.group_by_key_mut(|a| a.0);
    ///     
    ///     while let Some(slice) = it.next() {
    ///         for (i, pair) in slice.iter_mut().enumerate() {
    ///             pair.1 += i as i32;
    ///         }
    ///     }
    /// }
    /// assert_eq!(v, &[(0, 10), (0, 11), (1, 10), (1, 11), (1, 12)]);
    /// ```
    fn group_by_key_mut<'a, T: 'a, K, F>(&'a mut self, condition: F) -> GroupByKeyMut<'a, T, K, F>
        where Self: AsMut<[T]>, K: PartialEq, F: Fn(&T) -> K
    {
        GroupByKeyMut::new(self.as_mut(), condition)
    }

    /// Iterate on groups of equal items,
    /// yielding mutables references on slices.
    ///
    /// # Example
    ///
    /// ```
    /// use slicetools::*;
    ///
    /// let mut v = vec![0_i32, -1, -2, 2, 2, 2];
    /// {
    ///     let mut it = v.group_by_mut(|&a, &b| b.signum() == a.signum());
    ///     
    ///     while let Some(slice) = it.next() {
    ///         for (i, num) in slice.iter_mut().enumerate() {
    ///             *num += i as i32;
    ///         }
    ///     }
    /// }
    /// assert_eq!(v, &[0, -1, -1, 2, 3, 4]);
    /// ```
    fn group_by_mut<'a, T: 'a, F>(&'a mut self, condition: F) -> GroupByMut<'a, T, F>
        where Self: AsMut<[T]>, T: PartialEq, F: Fn(&T, &T) -> bool 
    {
        GroupByMut::new(self.as_mut(), condition)
    }
}

impl<T> SliceTools for T {}