fffl 1.2.0

A contiguous First-fit Freelist
Documentation
use std::{iter::FusedIterator, marker::PhantomData};

use crate::Slot;

use super::size_hint;

pub struct IterMutFl<'a, T: 'a> {
    start: *mut Slot<T>,
    end: *mut Slot<T>,
    _marker: PhantomData<&'a mut T>
}


impl<'a, T: 'a> IterMutFl<'a, T> {

    #[inline]
    pub(crate) const fn new(slice: &mut [Slot<T>]) -> Self {
        let start = slice.as_mut_ptr();
        Self {
            start,
            end: match slice.len() {
                0 => start,
                count @ _ => unsafe { start.add(count) }
            },
            _marker: PhantomData,
        }
    }
}

impl<'a, T: 'a> Iterator for IterMutFl<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        while self.start < self.end {
            let curr = self.start;
            unsafe {
                self.start = self.start.add(1);
                if let Slot::Value(value) = &mut *curr { return Some(value) }
            }
        }
        None
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        size_hint::<T>(self.start as usize, self.end as usize)
    }
}

impl<'a, T: 'a> DoubleEndedIterator for IterMutFl<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        while self.start < self.end {
            unsafe {
                self.end = self.end.offset(-1);
                if let Slot::Value(value) = &mut *self.end { return Some(value) }
            }
        }
        None
    }
}

impl<'a, T: 'a> FusedIterator for IterMutFl<'a, T> {}

impl<'a, T: 'a> Drop for IterMutFl<'a, T> {
    fn drop(&mut self) { for _ in &mut * self { } }
}


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

    #[test]
    fn next() {
        let slice = &mut [Slot::Empty, Slot::Value(1), Slot::Next(0), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);

        assert_eq!(iter.next(), Some(&mut 1)); 
        assert_eq!(iter.next(), Some(&mut 2));
        assert_eq!(iter.next(), None); 

        let slice = &mut [Slot::Value(0), Slot::Value(1), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);
        for mut i in [0, 1, 2] { 
            assert_eq!(iter.next(), Some(&mut i));
        }
        assert_eq!(iter.next(), None);
    }

        #[test]
    fn next_back() {
        let slice = &mut [Slot::Empty, Slot::Value(1), Slot::Next(0), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);

        assert_eq!(iter.next_back(), Some(&mut 2)); 
        assert_eq!(iter.next_back(), Some(&mut 1));
        assert_eq!(iter.next_back(), None);

        let slice = &mut [Slot::Value(0), Slot::Value(1), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);
        for mut i in [2, 1, 0] { 
            assert_eq!(iter.next_back(), Some(&mut i));
        }
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn size_hint() {
        let slice = &mut [Slot::Empty, Slot::Value(1), Slot::Next(0), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);
        assert_eq!(iter.size_hint(), (4, Some(4)));
        iter.next();
        assert_eq!(iter.size_hint(), (2, Some(2)));
    }

    #[test]
    fn update_value() {
        let slice = &mut [Slot::Empty, Slot::Value(1), Slot::Next(0), Slot::Value(2)];
        let mut iter = IterMutFl::new(slice);
        *iter.next().unwrap() = 11;
        assert_eq!(slice[1], Slot::Value(11));
    }
}