select_indices 3.0.1-alpha

Iterators for taking multiple shared/exclusive references from a slice
Documentation
use std::ops::IndexMut;
use crate::SelectIndicesIterMut;
use std::{
    collections::HashSet,
    hash::Hash,
};

pub struct SelectIndicesIndexedIterMut<'a, D, I>
where
    D: ?Sized,
    I: Iterator,
    I::Item: Copy + Hash + Eq,
{
    data: &'a mut D,
    index_iter: I,
    visited: HashSet<I::Item>
}

impl<'a, D, I> Iterator for SelectIndicesIndexedIterMut<'a, D, I>
where
    I: Iterator,
    I::Item: Copy + Hash + Eq,
    D: ?Sized + IndexMut<I::Item>,
    D::Output: 'a,
{
    type Item = (I::Item, &'a mut D::Output);

    fn next(&mut self) -> Option<Self::Item> {
        self.index_iter.next().map(|i| {
            assert!(self.visited.insert(i), "select_indices_mut was passed duplicate indices!");

            let ptr: *mut _ = self.data;
            (i, unsafe { ptr.as_mut().unwrap().index_mut(i) })
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.index_iter.size_hint()
    }
}

impl<'a, D, I> ExactSizeIterator for SelectIndicesIndexedIterMut<'a, D, I>
where
    I: ExactSizeIterator,
    I::Item: Copy + Hash + Eq,
    D: ?Sized + IndexMut<I::Item>,
    D::Output: 'a,
{}

impl<'a, D, I> DoubleEndedIterator for SelectIndicesIndexedIterMut<'a, D, I>
where
    I: DoubleEndedIterator,
    I::Item: Copy + Hash + Eq,
    D: ?Sized + IndexMut<I::Item>,
    D::Output: 'a,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.index_iter.next_back().map(|i| {
            assert!(self.visited.insert(i), "select_indices_mut was passed duplicate indices!");

            let ptr: *mut _ = self.data;
            (i, unsafe { ptr.as_mut().unwrap().index_mut(i) })
        })
    }
}

impl<'a, D, I> SelectIndicesIterMut<'a, D, I>
where
    D: ?Sized,
    I: Iterator,
    I::Item: Copy + Hash + Eq,
{
    pub fn indexed(self) -> SelectIndicesIndexedIterMut<'a, D, I>
    {
        SelectIndicesIndexedIterMut {
            data: self.data,
            index_iter: self.index_iter,
            visited: self.visited,
        }
    }
}