use core::borrow::{Borrow, BorrowMut};
use core::fmt;
use core::mem::{ManuallyDrop, MaybeUninit};
use core::ops::{Deref, DerefMut};
pub struct Full<T>(pub T);
impl<T> Full<T> {
#[inline]
pub fn into_inner(self) -> T {
self.0
}
}
impl<T> fmt::Debug for Full<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("Full(..)")
}
}
impl<T> fmt::Display for Full<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("allocator full")
}
}
#[cfg(feature = "std")]
impl<T> std::error::Error for Full<T> {}
#[repr(C)]
pub union SlotCell<T> {
next_free: *mut SlotCell<T>,
value: ManuallyDrop<MaybeUninit<T>>,
}
impl<T> SlotCell<T> {
#[inline]
pub(crate) fn vacant(next_free: *mut SlotCell<T>) -> Self {
SlotCell { next_free }
}
#[inline]
pub(crate) unsafe fn write_value(&mut self, value: T) {
self.value = ManuallyDrop::new(MaybeUninit::new(value));
}
#[inline]
pub(crate) unsafe fn read_value(&self) -> T {
unsafe { core::ptr::read(self.value.as_ptr()) }
}
#[inline]
pub(crate) unsafe fn drop_value_in_place(&mut self) {
unsafe {
core::ptr::drop_in_place((*self.value).as_mut_ptr());
}
}
#[inline]
pub unsafe fn value_ref(&self) -> &T {
unsafe { self.value.assume_init_ref() }
}
#[inline]
pub unsafe fn value_mut(&mut self) -> &mut T {
unsafe { (*self.value).assume_init_mut() }
}
#[inline]
pub unsafe fn value_ptr(&self) -> *const T {
unsafe { self.value.as_ptr() }
}
#[inline]
pub unsafe fn value_ptr_mut(ptr: *mut SlotCell<T>) -> *mut T {
ptr.cast::<T>()
}
#[inline]
pub(crate) unsafe fn get_next_free(&self) -> *mut SlotCell<T> {
unsafe { self.next_free }
}
#[inline]
pub(crate) unsafe fn set_next_free(&mut self, next: *mut SlotCell<T>) {
self.next_free = next;
}
}
#[repr(transparent)]
pub struct Slot<T>(*mut SlotCell<T>);
impl<T> Slot<T> {
#[inline]
pub(crate) unsafe fn from_ptr(ptr: *mut SlotCell<T>) -> Self {
Slot(ptr)
}
#[inline]
pub fn as_ptr(&self) -> *mut SlotCell<T> {
self.0
}
#[inline]
pub fn into_raw(self) -> *mut SlotCell<T> {
let ptr = self.0;
core::mem::forget(self);
ptr
}
#[inline]
pub unsafe fn from_raw(ptr: *mut SlotCell<T>) -> Self {
Slot(ptr)
}
#[inline]
pub unsafe fn clone_ptr(&self) -> Self {
Slot(self.0)
}
#[inline]
pub fn pin(&self) -> core::pin::Pin<&T> {
unsafe { core::pin::Pin::new_unchecked(&**self) }
}
#[inline]
pub fn pin_mut(&mut self) -> core::pin::Pin<&mut T> {
unsafe { core::pin::Pin::new_unchecked(&mut **self) }
}
}
impl<T> Deref for Slot<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { (*self.0).value_ref() }
}
}
impl<T> DerefMut for Slot<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { (*self.0).value_mut() }
}
}
impl<T> AsRef<T> for Slot<T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T> AsMut<T> for Slot<T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T> Borrow<T> for Slot<T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<T> BorrowMut<T> for Slot<T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<T: fmt::Debug> fmt::Debug for Slot<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Slot").field("value", &**self).finish()
}
}
#[cfg(debug_assertions)]
impl<T> Drop for Slot<T> {
fn drop(&mut self) {
#[cfg(feature = "std")]
if std::thread::panicking() {
return; }
panic!(
"Slot<{}> dropped without being freed — call slab.free(slot) or slab.take(slot)",
core::any::type_name::<T>()
);
}
}