eziter 0.1.2

Wrapper around Iterator
Documentation
use paste::paste;
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};

macro_rules! eziter {
    ($(
        $(($($template:ident),+))? $name:ident ( $($arg:ty),* ) -> $fret:ty => $col:ty,
    )*) => {

        pub trait EzRefIterator<'a>: RefIterator<'a> {
            $(
                fn $name<F, C $($(, $template)+)? >(&'a self, f: F) -> C
                where
                    Self: Sized,
                    F: FnMut($($arg),*) -> $fret,
                    C: std::iter::FromIterator<$col>,
                {
                    Iterator::$name(self.iter_ref(), f).collect()
                }
            )*
        }

        pub trait EzIntoIterator: IntoIterator {
            $(
                paste! {
                    fn [<into_ $name>]<F, C $($(, $template)+)? >(self, f: F) -> C
                    where
                        Self: Sized,
                        F: FnMut($($arg),*) -> $fret,
                        C: std::iter::FromIterator<$col>,
                    {
                        Iterator::$name(self.into_iter(), f).collect()
                    }
                }
            )*
        }

        pub trait EzMutIterator<'a>: MutIterator<'a> {
            $(
                paste! {
                    fn [<$name _mut>]<F, C $($(, $template)+)? >(&'a mut self, f: F) -> C
                    where
                        Self: Sized,
                        F: FnMut($($arg),*) -> $fret,
                        C: std::iter::FromIterator<$col>,
                    {
                        Iterator::$name(self.mut_iter(), f).collect()
                    }
                }
            )*
        }
    };
}

eziter! {
    (R) map(Self::Item) -> R => R,
    filter(&Self::Item) -> bool => Self::Item,
    filter_map(Self::Item) -> Option<Self::Item> => Self::Item,
    skip_while(&Self::Item) -> bool => Self::Item,
    take_while(&Self::Item) -> bool => Self::Item,
    (B) map_while(Self::Item) -> Option<B> => B,
}

pub trait RefIterator<'a> {
    type Item;

    fn iter_ref(&'a self) -> Box<dyn Iterator<Item = Self::Item> + '_>;
}

pub trait MutIterator<'a> {
    type Item;

    fn mut_iter(&'a mut self) -> Box<dyn Iterator<Item = Self::Item> + '_>;
}

macro_rules! impl_eziter_ref {
    ($(
        $name:ty{$($param:ident),*},
    )*) => {
        $(
            impl<'a, $($param: 'a),*> RefIterator<'a> for $name {
                #[allow(unused_parens)]
                type Item = ($(&'a $param),*);

                fn iter_ref(&'a self) -> Box<dyn Iterator<Item = Self::Item> + '_> {
                    Box::new(self.iter())
                }
            }
        )*
    };
}

impl_eziter_ref! {
    HashMap<K, V>{K, V},
    BTreeMap<K, V>{K, V},
    HashSet<K>{K},
    BTreeSet<K>{K},
    BinaryHeap<T>{T},
    LinkedList<T>{T},
    Vec<T>{T},
    VecDeque<T>{T},
}

macro_rules! impl_eziter_mut {
    ($(
        $name:ty{$($param:ident),*}$item_mut:ty,
    )*) => {
        $(
            impl<'a, $($param: 'a),*> MutIterator<'a> for $name {
                #[allow(unused_parens)]
                type Item = $item_mut;

                fn mut_iter(&'a mut self) -> Box<dyn Iterator<Item = Self::Item> + '_> {
                    Box::new(self.iter_mut())
                }
            }
        )*
    };
}

impl_eziter_mut! {
    HashMap<K, V>{K, V}(&'a K, &'a mut V),
    BTreeMap<K, V>{K, V}(&'a K, &'a mut V),
    LinkedList<T>{T}(&'a mut T),
    Vec<T>{T}(&'a mut T),
    VecDeque<T>{T}(&'a mut T),
}

impl<T> EzIntoIterator for T where T: IntoIterator {}
impl<'a, T> EzRefIterator<'a> for T where T: RefIterator<'a> {}
impl<'a, T> EzMutIterator<'a> for T where T: MutIterator<'a> {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let v = vec![1, 2];
        let h: BTreeMap<_, _> = v.into_map(|x| (x, x));
        let mut v2: Vec<_> = h.map(|(k, v)| k + v);
        let v3: Vec<_> = v2.map_mut(|v| *v + 1);

        assert_eq!(v3.get(0), Some(&3));
        assert_eq!(v3.get(1), Some(&5));
    }
}