cds 0.10.0

Collection of Optimized Data Structures
Documentation
use crate::{len::LengthType, mem::SpareMemoryPolicy, smallvec::SmallVec};
use core::{
    marker::PhantomData,
    mem::{ManuallyDrop, MaybeUninit},
};

pub struct Local<T, const C: usize, SM>
where
    SM: SpareMemoryPolicy<T>,
{
    pub arr: [MaybeUninit<T>; C],
    phantom: PhantomData<SM>,
}

impl<T, const C: usize, SM> Local<T, C, SM>
where
    SM: SpareMemoryPolicy<T>,
{
    #[inline(always)]
    fn new() -> Self {
        let mut local = Self {
            arr: unsafe { MaybeUninit::uninit().assume_init() },
            phantom: PhantomData,
        };
        unsafe {
            SM::init(local.arr.as_mut_ptr() as *mut T, C);
        }
        local
    }
}

pub union Buffer<T, const C: usize, L, SM>
where
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
    local: ManuallyDrop<Local<T, C, SM>>,
    heap: (*const T, L),
}

unsafe impl<T, const C: usize, L, SM> Send for Buffer<T, C, L, SM>
where
    T: Send,
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
}

unsafe impl<T, const C: usize, L, SM> Sync for Buffer<T, C, L, SM>
where
    T: Sync,
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
}

impl<T, const C: usize, L, SM> Buffer<T, C, L, SM>
where
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
    #[inline(always)]
    pub fn new() -> Self {
        Self {
            local: ManuallyDrop::new(Local::new()),
        }
    }

    #[inline]
    pub fn heap_len(&self) -> L {
        unsafe { self.heap.1 }
    }

    #[inline]
    pub fn heap_ptr(&self) -> *const T {
        unsafe { self.heap.0 }
    }

    #[inline]
    pub fn heap_mut_ptr(&mut self) -> *mut T {
        unsafe { self.heap.0 as *mut T }
    }

    #[inline]
    pub fn set_heap(&mut self, p: *mut T, l: L) {
        self.heap.0 = p;
        self.heap.1 = l;
    }

    #[inline]
    pub fn set_heap_ptr(&mut self, p: *mut T) {
        self.heap.0 = p;
    }

    #[inline]
    pub fn set_heap_len(&mut self, l: L) {
        self.heap.1 = l;
    }

    #[inline]
    pub fn heap_len_add_assign(&mut self, c: usize) {
        unsafe { self.heap.1.add_assign(c) }
    }

    #[inline]
    pub fn local_ptr(&self) -> *const T {
        unsafe { self.local.arr.as_ptr() as *const T }
    }

    #[inline]
    pub fn local_mut_ptr(&mut self) -> *mut T {
        unsafe { self.local.arr.as_mut_ptr() as *mut T }
    }

    #[inline]
    pub fn heap_len_p(&self) -> (L, *const T) {
        unsafe { (self.heap.1, self.heap.0) }
    }

    #[inline]
    pub fn heap_len_mut_p(&mut self) -> (L, *mut T) {
        unsafe { (self.heap.1, self.heap.0 as *mut T) }
    }

    #[inline]
    pub fn heap_mut_len_mut_p(&mut self) -> (&mut L, *mut T) {
        unsafe { (&mut self.heap.1, self.heap.0 as *mut T) }
    }
}

#[derive(Debug)]
pub struct SetLenOnDrop<'a, T, const C: usize, L, SM>
where
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
    pub len: usize,
    pub sv: &'a mut SmallVec<T, C, L, SM>,
    pub armed: bool,
}

impl<'a, T, const C: usize, L, SM> SetLenOnDrop<'a, T, C, L, SM>
where
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
    #[inline]
    pub fn new(sv: &'a mut SmallVec<T, C, L, SM>, len: usize) -> Self {
        Self {
            len,
            sv,
            armed: true,
        }
    }

    #[inline]
    pub fn unarmed(sv: &'a mut SmallVec<T, C, L, SM>, len: usize) -> Self {
        Self {
            len,
            sv,
            armed: false,
        }
    }
}

impl<'a, T, const C: usize, L, SM> Drop for SetLenOnDrop<'a, T, C, L, SM>
where
    L: LengthType,
    SM: SpareMemoryPolicy<T>,
{
    #[inline]
    fn drop(&mut self) {
        if self.armed {
            unsafe { self.sv.set_len(self.len) }
        }
    }
}