orx-split-vec 4.0.0

An efficient dynamic capacity vector with pinned element guarantees.
Documentation
use crate::{
    GrowthWithConstantTimeAccess, concurrent_pinned_vec::iter_ptr_slices::IterPtrOfConSlices,
};
use core::{cell::UnsafeCell, ops::Range};

pub struct IterPtrOfCon<'a, T, G>
where
    G: GrowthWithConstantTimeAccess,
{
    slices: IterPtrOfConSlices<'a, T, G>,
    len_of_remaining_slices: usize,
    current_ptr: *const T,
    current_len: usize,
}

impl<'a, T, G> Default for IterPtrOfCon<'a, T, G>
where
    G: GrowthWithConstantTimeAccess,
{
    fn default() -> Self {
        Self {
            slices: IterPtrOfConSlices::default(),
            len_of_remaining_slices: 0,
            current_ptr: core::ptr::null(),
            current_len: 0,
        }
    }
}

impl<'a, T, G> IterPtrOfCon<'a, T, G>
where
    G: GrowthWithConstantTimeAccess,
{
    pub fn new(
        capacity: usize,
        fragments: &'a [UnsafeCell<*mut T>],
        growth: G,
        range: Range<usize>,
    ) -> Self {
        let len_of_remaining_slices = range.len();
        let slices = IterPtrOfConSlices::new(capacity, fragments, growth, range);
        Self {
            slices,
            len_of_remaining_slices,
            current_ptr: core::ptr::null(),
            current_len: 0,
        }
    }

    fn remaining(&self) -> usize {
        let remaining_current = match self.current_ptr.is_null() {
            true => 0,
            false => self.current_len,
        };

        self.len_of_remaining_slices + remaining_current
    }

    fn next_slice(&mut self) -> Option<*mut T> {
        self.slices.next().and_then(|(ptr, len)| {
            debug_assert!(len > 0);
            self.len_of_remaining_slices -= len;
            // SAFETY: pointers are not null since slice is not empty
            self.current_ptr = ptr;
            self.current_len = len;
            self.next()
        })
    }
}

impl<'a, T, G> Iterator for IterPtrOfCon<'a, T, G>
where
    G: GrowthWithConstantTimeAccess,
{
    type Item = *mut T;

    fn next(&mut self) -> Option<Self::Item> {
        match self.current_ptr {
            ptr if ptr.is_null() => self.next_slice(),
            ptr if self.current_len == 1 => {
                self.current_ptr = core::ptr::null_mut();
                self.current_len = 0;
                Some(ptr as *mut T)
            }
            ptr => {
                self.current_len -= 1;
                // SAFETY: current_ptr is not the last element, hance current_ptr+1 is in bounds
                self.current_ptr = unsafe { self.current_ptr.add(1) };

                // SAFETY: ptr is valid and its value can be taken.
                // Drop will skip this position which is now uninitialized.
                Some(ptr as *mut T)
            }
        }
    }

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

impl<'a, T, G> ExactSizeIterator for IterPtrOfCon<'a, T, G>
where
    G: GrowthWithConstantTimeAccess,
{
    fn len(&self) -> usize {
        self.remaining()
    }
}