read-write-store 0.2.0

A concurrent, unordered collection for Rust, where each element has an internally generated ID and a read-write lock.
Documentation
use std::fmt::Debug;
#[cfg(debug_assertions)]
use std::mem::ManuallyDrop;
#[cfg(not(debug_assertions))]
use std::mem::MaybeUninit;
use std::ptr::NonNull;

pub trait IndexDebugChecked<T> {
    unsafe fn get_debug_checked(&self, index: usize) -> &T;
    unsafe fn get_debug_checked_mut(&mut self, index: usize) -> &mut T;
}

impl<T> IndexDebugChecked<T> for [T] {
    unsafe fn get_debug_checked(&self, index: usize) -> &T {
        if cfg!(debug_assertions) {
            &self[index]
        } else {
            self.get_unchecked(index)
        }
    }

    unsafe fn get_debug_checked_mut(&mut self, index: usize) -> &mut T {
        if cfg!(debug_assertions) {
            &mut self[index]
        } else {
            self.get_unchecked_mut(index)
        }
    }
}

pub trait UnwrapDebugChecked<T> {
    unsafe fn unwrap_debug_checked(self) -> T;
}

impl<T> UnwrapDebugChecked<T> for Option<T> {
    unsafe fn unwrap_debug_checked(self) -> T {
        if cfg!(debug_assertions) {
            self.unwrap()
        } else {
            self.unwrap_unchecked()
        }
    }
}

impl<T, E: Debug> UnwrapDebugChecked<T> for Result<T, E> {
    unsafe fn unwrap_debug_checked(self) -> T {
        if cfg!(debug_assertions) {
            self.unwrap()
        } else {
            self.unwrap_unchecked()
        }
    }
}

pub trait NewDebugChecked<T> {
    unsafe fn new_debug_checked(value: T) -> Self;
}

impl<T> NewDebugChecked<*mut T> for NonNull<T> {
    unsafe fn new_debug_checked(value: *mut T) -> Self {
        if cfg!(debug_assertions) {
            NonNull::new(value).unwrap()
        } else {
            NonNull::new_unchecked(value)
        }
    }
}

#[repr(transparent)]
#[cfg(debug_assertions)]
pub struct DebugCheckedMaybeUninit<T> {
    inner: ManuallyDrop<Option<T>>,
}

#[cfg(debug_assertions)]
impl<T> DebugCheckedMaybeUninit<T> {
    pub fn uninit() -> Self {
        Self {
            inner: ManuallyDrop::new(None),
        }
    }

    pub fn new(value: T) -> Self {
        Self {
            inner: ManuallyDrop::new(Some(value)),
        }
    }

    pub unsafe fn assume_init(self) -> T {
        ManuallyDrop::into_inner(self.inner).unwrap()
    }

    pub unsafe fn contents_ptr(&self) -> NonNull<T> {
        match self.inner.as_ref() {
            Some(value) => NonNull::new_debug_checked(value as *const _ as *mut _),
            None => unreachable!(),
        }
    }
}

#[repr(transparent)]
#[cfg(not(debug_assertions))]
pub struct DebugCheckedMaybeUninit<T> {
    inner: MaybeUninit<T>,
}

#[cfg(not(debug_assertions))]
impl<T> DebugCheckedMaybeUninit<T> {
    pub fn uninit() -> Self {
        Self {
            inner: MaybeUninit::uninit(),
        }
    }

    pub fn new(value: T) -> Self {
        Self {
            inner: MaybeUninit::new(value),
        }
    }

    pub unsafe fn assume_init(self) -> T {
        self.inner.assume_init()
    }

    pub unsafe fn contents_ptr(&self) -> NonNull<T> {
        NonNull::new_debug_checked(self as *const _ as *mut _)
    }
}