chunked_vec 0.5.1

A chunk-oriented vector collection with fixed-size chunk storage
Documentation
use std::iter::FusedIterator;

use crate::{Chunk, ChunkedVec};

/// A mutable iterator over fully initialized chunks of a [`ChunkedVec`].
///
/// This struct is created by the [`iter_full_chunks_mut`] method on
/// [`ChunkedVec`].
pub struct FullChunksMut<'a, T, const N: usize> {
    pub(crate) inner: std::slice::IterMut<'a, Chunk<T, N>>,
}

impl<T, const N: usize> ChunkedVec<T, N> {
    /// Returns an iterator over fully initialized chunks as mutable fixed-size
    /// arrays.
    ///
    /// This excludes the trailing partial chunk when the vector length is not
    /// a multiple of `N`.
    ///
    /// # Examples
    /// ```
    /// use chunked_vec::{ChunkedVec, ChunkedVecSized};
    ///
    /// let mut vec: ChunkedVec<i32, 4> = ChunkedVecSized::new();
    /// vec.extend(0..10);
    ///
    /// for chunk in vec.iter_full_chunks_mut() {
    ///     chunk[0] *= 10;
    /// }
    ///
    /// assert_eq!(vec.full_chunk(0), Some(&[0, 1, 2, 3]));
    /// assert_eq!(vec.full_chunk(1), Some(&[40, 5, 6, 7]));
    /// assert_eq!(vec.remainder(), Some(&[8, 9][..]));
    /// ```
    pub fn iter_full_chunks_mut(&mut self) -> FullChunksMut<'_, T, N> {
        let full_chunk_count = self.full_chunk_count();

        FullChunksMut {
            inner: self.data[..full_chunk_count].iter_mut(),
        }
    }
}

impl<'a, T, const N: usize> Iterator for FullChunksMut<'a, T, N> {
    type Item = &'a mut [T; N];

    fn next(&mut self) -> Option<Self::Item> {
        let chunk = self.inner.next()?;
        let ptr = chunk.as_mut() as *mut _ as *mut [T; N];

        unsafe { Some(&mut *ptr) }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.inner.len();
        (remaining, Some(remaining))
    }
}

impl<T, const N: usize> ExactSizeIterator for FullChunksMut<'_, T, N> {}

impl<T, const N: usize> FusedIterator for FullChunksMut<'_, T, N> {}

#[cfg(test)]
mod tests {
    use crate::{ChunkedVec, ChunkedVecSized};

    #[test]
    fn test_iter_full_chunks_mut() {
        let mut vec: ChunkedVec<i32, 4> = ChunkedVecSized::new();
        vec.extend(0..10);

        for chunk in vec.iter_full_chunks_mut() {
            chunk[0] += 10;
        }

        let chunks: Vec<&[i32; 4]> = vec.iter_full_chunks().collect();
        assert_eq!(chunks, vec![&[10, 1, 2, 3], &[14, 5, 6, 7]]);
        assert_eq!(vec.remainder(), Some(&[8, 9][..]));
    }

    #[test]
    fn test_iter_full_chunks_mut_empty() {
        let mut vec: ChunkedVec<i32, 4> = ChunkedVecSized::new();
        assert_eq!(vec.iter_full_chunks_mut().next(), None);
    }
}