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 PtrBackward<T> {
    current: Option<*const T>,
    stopper: *const T,
}

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

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

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

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

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

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

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

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

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

    #[test]
    fn ptr_bwd_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 = PtrBackward::from(&fragment);
        for i in (0..9).rev() {
            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_bwd_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 = PtrBackward::from(&fragment);
        for i in (0..14).rev() {
            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);
    }
}