orx-split-vec 3.22.0

An efficient dynamic capacity vector with pinned element guarantees.
Documentation
use crate::Fragment;
use core::iter::FusedIterator;

#[derive(PartialEq, Eq, Debug, Copy)]
pub struct Ptr<T> {
    current: *const T,
    stopper: *const T,
}

impl<T> Default for Ptr<T> {
    fn default() -> Self {
        Self {
            current: core::ptr::null(),
            stopper: core::ptr::null(),
        }
    }
}

impl<T> Clone for Ptr<T> {
    fn clone(&self) -> Self {
        Self {
            current: self.current,
            stopper: self.stopper,
        }
    }
}

impl<'a, T> From<&'a Fragment<T>> for Ptr<T> {
    fn from(value: &'a Fragment<T>) -> Self {
        match value.len() {
            0 => Self::default(),
            _ => {
                let current = value.as_ptr();
                let stopper = unsafe { current.add(value.len()) };
                Self { current, stopper }
            }
        }
    }
}

impl<T> Iterator for Ptr<T> {
    type Item = *const T;

    fn next(&mut self) -> Option<Self::Item> {
        let p = self.current;
        match p == self.stopper {
            false => {
                self.current = unsafe { self.current.add(1) };
                Some(p)
            }
            true => None,
        }
    }
}

impl<T> FusedIterator for Ptr<T> {}

#[cfg(test)]
mod tests {
    use super::*;
    use alloc::{
        string::{String, ToString},
        vec::Vec,
    };

    #[test]
    fn ptr_empty_fragment() {
        let fragment: Fragment<String> = Vec::with_capacity(0).into();

        let mut iter = Ptr::from(&fragment);
        assert_eq!(iter.next(), None);
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn ptr_half_full_fragment() {
        let mut fragment: Fragment<String> = Vec::with_capacity(14).into();
        for i in 0..9 {
            fragment.push(i.to_string());
        }

        let mut iter = Ptr::from(&fragment);
        for i in 0..9 {
            let val = iter.next().map(|p| unsafe { &*p });
            assert_eq!(val, Some(&i.to_string()));
        }

        assert_eq!(iter.next(), None);
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn ptr_full_fragment() {
        let mut fragment: Fragment<String> = Vec::with_capacity(14).into();
        for i in 0..14 {
            fragment.push(i.to_string());
        }

        let mut iter = Ptr::from(&fragment);
        for i in 0..14 {
            let val = iter.next().map(|p| unsafe { &*p });
            assert_eq!(val, Some(&i.to_string()));
        }

        assert_eq!(iter.next(), None);
        assert_eq!(iter.next(), None);
    }
}