strmap 1.0.0

A map using strings or paths as keys
Documentation
use std::mem::MaybeUninit;

use crate::bit_vec::BitVec;

pub(crate) struct DelVec<T> {
    size: usize,
    deleted: BitVec,
    data: Box<[MaybeUninit<T>]>,
}

unsafe fn assume_init<T>(r: &MaybeUninit<T>) -> &T {
    &*(r as *const MaybeUninit<T> as *const T)
}

unsafe fn assume_init_mut<T>(r: &mut MaybeUninit<T>) -> &mut T {
    &mut *(r as *mut MaybeUninit<T> as *mut T)
}

impl<T> DelVec<T> {
    pub(crate) fn new(vals: Vec<T>) -> Self {
        Self {
            size: vals.len(),
            deleted: BitVec::new(vals.len()),
            data: unsafe {
                // SAFETY: T and MaybeUninit<T> have the same layout.
                let vals = vals.into_boxed_slice();
                Box::from_raw(Box::into_raw(vals) as *mut [MaybeUninit<T>])
            },
        }
    }

    pub(crate) fn len(&self) -> usize {
        self.size
    }

    pub(crate) fn capacity(&self) -> usize {
        self.data.len()
    }

    pub(crate) fn get(&self, idx: usize) -> Option<&T> {
        if idx >= self.data.len() || self.deleted.get(idx) {
            return None;
        }
        // SAFETY: We just checked that this index contains a valid value.
        unsafe { Some(assume_init(self.data.get_unchecked(idx))) }
    }

    pub(crate) fn get_mut(&mut self, idx: usize) -> Option<&mut T> {
        if idx >= self.data.len() || self.deleted.get(idx) {
            return None;
        }
        // SAFETY: We just checked that this index contains a valid value.
        unsafe { Some(assume_init_mut(self.data.get_unchecked_mut(idx))) }
    }

    pub(crate) fn take(&mut self, idx: usize) -> Option<T> {
        if idx >= self.data.len() || self.deleted.get(idx) {
            return None;
        }
        self.deleted.set(idx);
        self.size -= 1;
        // SAFETY: We just checked that this index contains a valid value,
        // and by setting it to deleted, it is ok to give away ownership.
        unsafe { Some(std::ptr::read(assume_init(self.data.get_unchecked(idx)))) }
    }

    pub(crate) fn delete(&mut self, idx: usize) -> bool {
        if idx >= self.data.len() || self.deleted.get(idx) {
            return false;
        }
        self.deleted.set(idx);
        self.size -= 1;
        // SAFETY: We just checked that this index contains a valid value,
        // and by setting it to deleted, it is ok to destroy it.
        unsafe {
            let ptr: *mut T = self.data.as_mut_ptr().add(idx).cast();
            std::ptr::drop_in_place(ptr);
        }
        true
    }
}

impl<T> Drop for DelVec<T> {
    fn drop(&mut self) {
        for i in 0..self.data.len() {
            if !self.deleted.get(i) {
                // SAFETY: We just checked that this index has not yet been
                // deleted.
                unsafe {
                    let ptr: *mut T = self.data.as_mut_ptr().add(i).cast();
                    std::ptr::drop_in_place(ptr);
                }
            }
        }
    }
}