use std::marker::PhantomData;
use std::pin::Pin;
use std::ptr::NonNull;
use crate::*;
#[repr(transparent)]
pub struct Slot<T, S: Policy>(pub(crate) NonNull<Entry<T>>, PhantomData<T>, PhantomData<S>);
unsafe impl<T: Send, S: Policy> Send for Slot<T, S> {}
unsafe impl<T: Sync, S: Policy> Sync for Slot<T, S> {}
impl<T, S: Policy> Slot<T, S> {
pub(crate) fn new(from: NonNull<Entry<T>>) -> Self {
Self(from, PhantomData, PhantomData)
}
}
pub trait Policy {}
pub trait DropPolicy: Policy {
#[inline]
#[doc(hidden)]
fn manually_drop<T>(data: &mut std::mem::ManuallyDrop<T>) {
unsafe { std::mem::ManuallyDrop::drop(data) };
}
}
pub trait CanGetReference: Policy {}
pub trait CanTakeValue: Policy {}
pub enum Uninitialized {}
impl Policy for Uninitialized {}
impl DropPolicy for Uninitialized {
#[inline]
fn manually_drop<T>(_data: &mut std::mem::ManuallyDrop<T>) {}
}
pub enum Initialized {}
impl Policy for Initialized {}
impl DropPolicy for Initialized {}
impl CanGetReference for Initialized {}
impl CanTakeValue for Initialized {}
pub enum Mutable {}
impl Policy for Mutable {}
impl DropPolicy for Mutable {}
impl CanGetReference for Mutable {}
impl CanTakeValue for Mutable {}
pub enum Pinnable {}
impl Policy for Pinnable {}
impl DropPolicy for Pinnable {}
impl CanGetReference for Pinnable {}
impl CanTakeValue for Pinnable {}
pub enum NaNTagging {}
impl Policy for NaNTagging {}
impl DropPolicy for NaNTagging {}
impl CanGetReference for NaNTagging {}
impl CanTakeValue for NaNTagging {}
impl<T> Slot<T, Uninitialized> {
#[inline]
pub fn get_uninit(&mut self) -> &mut Entry<T> {
unsafe { self.0.as_mut() }
}
#[inline]
#[must_use]
pub unsafe fn assume_init(self) -> Slot<T, Initialized> {
Slot::<T, Initialized>(self.0, PhantomData, PhantomData)
}
}
impl<T> Slot<T, Initialized> {
#[inline]
#[must_use]
pub fn for_mutation(self) -> Slot<T, Mutable> {
Slot(self.0, PhantomData, PhantomData)
}
#[inline]
#[must_use]
pub fn for_pinning(self) -> Slot<T, Pinnable> {
Slot(self.0, PhantomData, PhantomData)
}
#[inline]
#[must_use]
pub fn for_nantagging(self) -> Slot<T, NaNTagging> {
Slot(self.0, PhantomData, PhantomData)
}
}
impl<T> Slot<T, Mutable> {
#[inline]
pub fn get_mut(&mut self) -> &mut T {
unsafe { &mut self.0.as_mut().data }
}
#[inline]
#[must_use]
pub unsafe fn copy(&self) -> Self {
Slot(self.0, PhantomData, PhantomData)
}
}
impl<T> Slot<T, Pinnable> {
pub fn get_pin(&mut self) -> Pin<&mut T> {
unsafe { Pin::new_unchecked(&mut self.0.as_mut().data) }
}
}
impl<T, S: CanGetReference> Slot<T, S> {
#[inline]
#[must_use]
pub fn get(&self) -> &T {
unsafe { &self.0.as_ref().data }
}
}
impl<T> Slot<T, NaNTagging> {
#[inline]
#[must_use]
pub fn into_u64(self) -> u64 {
debug_assert_eq!(
self.0.as_ptr() as u64 & 0xffff000000000007,
0,
"Something is wrong on this platform"
);
self.0.as_ptr() as u64
}
#[inline]
#[must_use]
pub unsafe fn from_u64(id: u64) -> Self {
debug_assert_eq!(id & 0xffff000000000007, 0, "Invalid identifier");
Self(
NonNull::new(id as *mut Entry<T>).expect("Invalid identifier"),
PhantomData,
PhantomData,
)
}
#[inline]
#[must_use]
pub unsafe fn from_u64_masked(id: u64) -> Self {
Self(
NonNull::new((id & !0xffff000000000007) as *mut Entry<T>).expect("Invalid identifier"),
PhantomData,
PhantomData,
)
}
}