use core::{
cell::UnsafeCell, convert::AsMut, marker::PhantomData, mem::MaybeUninit, num::NonZeroUsize,
};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
pub unsafe trait Container<T> {
fn len(&self) -> usize;
#[inline]
fn is_empty(&self) -> bool {
self.len() == 0
}
fn as_mut_slice(&mut self) -> &mut [MaybeUninit<T>];
#[inline]
fn as_mut_ptr(&mut self) -> *mut MaybeUninit<T> {
self.as_mut_slice().as_mut_ptr()
}
}
unsafe impl<'a, T> Container<T> for &'a mut [MaybeUninit<T>] {
#[inline]
fn len(&self) -> usize {
<[_]>::len(self)
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] {
self
}
}
unsafe impl<T, const N: usize> Container<T> for [MaybeUninit<T>; N] {
#[inline]
fn len(&self) -> usize {
N
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] {
self.as_mut()
}
}
#[cfg(feature = "alloc")]
unsafe impl<T> Container<T> for Vec<MaybeUninit<T>> {
#[inline]
fn len(&self) -> usize {
self.len()
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [MaybeUninit<T>] {
self.as_mut()
}
}
pub(crate) struct SharedStorage<T, C: Container<T>> {
container: UnsafeCell<C>,
_phantom: PhantomData<T>,
}
unsafe impl<T, C: Container<T>> Sync for SharedStorage<T, C> where T: Send {}
impl<T, C: Container<T>> SharedStorage<T, C> {
pub fn new(container: C) -> Self {
assert!(!container.is_empty());
Self {
container: UnsafeCell::new(container),
_phantom: PhantomData,
}
}
#[inline]
pub fn len(&self) -> NonZeroUsize {
unsafe { NonZeroUsize::new_unchecked((*self.container.get()).len()) }
}
#[allow(clippy::mut_from_ref)]
#[inline]
pub unsafe fn as_slice(&self) -> &mut [MaybeUninit<T>] {
(*self.container.get()).as_mut_slice()
}
pub fn into_inner(self) -> C {
self.container.into_inner()
}
}