chunked_vec 0.5.1

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

use crate::{Chunk, ChunkedVec};

/// An iterator over the logical chunks of a [`ChunkedVec`].
///
/// This struct is created by the [`iter_chunks`] method on [`ChunkedVec`].
pub struct Chunks<'a, T, const N: usize> {
    pub(crate) inner: std::slice::Iter<'a, Chunk<T, N>>,
    pub(crate) remaining_len: usize,
}

impl<T, const N: usize> ChunkedVec<T, N> {
    /// Returns an iterator over the logical chunks of the vector.
    ///
    /// Each item is a slice containing the initialized elements of one chunk.
    /// The last chunk may be shorter than `N`.
    ///
    /// # Examples
    /// ```
    /// use chunked_vec::{ChunkedVec, ChunkedVecSized};
    ///
    /// let mut vec: ChunkedVec<i32, 4> = ChunkedVecSized::new();
    /// vec.extend(0..6);
    ///
    /// let chunks: Vec<&[i32]> = vec.iter_chunks().collect();
    /// assert_eq!(chunks, vec![&[0, 1, 2, 3][..], &[4, 5][..]]);
    /// ```
    pub fn iter_chunks(&self) -> Chunks<'_, T, N> {
        let chunk_count = self.chunk_count();

        Chunks {
            inner: self.data[..chunk_count].iter(),
            remaining_len: self.len(),
        }
    }
}

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

    fn next(&mut self) -> Option<Self::Item> {
        let chunk = self.inner.next()?;
        let len = self.remaining_len.min(N);
        self.remaining_len -= len;

        unsafe { Some(std::slice::from_raw_parts(chunk.as_ptr().cast::<T>(), len)) }
    }

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

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

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

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

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

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

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