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 IterFl<'a, T: 'a> {
    start: *const Slot<T>,
    end: *const Slot<T>,
    _marker: PhantomData<&'a T>
}


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

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


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

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

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

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


#[cfg(test)]
mod tests {
    use super::*;
    static SLICE: &[Slot<i32>] = &[Slot::Empty, Slot::Value(1), Slot::Next(0), Slot::Value(2)];
    const ALL_SLICE: &[Slot<i32>; 3] = &[Slot::Value(0), Slot::Value(1), Slot::Value(2)];

    #[test]
    fn next() {
        let mut iter = IterFl::new(SLICE);

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

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

    #[test]
    fn next_back() {
        let mut iter = IterFl::new(SLICE);

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

        let mut iter = IterFl::new(ALL_SLICE);
        for i in [2, 1, 0] { 
            assert_eq!(iter.next_back(), Some(&i));
        }
        assert_eq!(iter.next_back(), None);
    }

    #[test]
    fn size_hint() {
        let mut iter = IterFl::new(SLICE);

        assert_eq!(iter.size_hint(), (4, Some(4)));
        iter.next();
        assert_eq!(iter.size_hint(), (2, Some(2)));
    }
}