use core::marker::PhantomData;
#[derive(Clone, Copy)]
#[repr(C, align(8))]
pub struct AlignedBytes<const N: usize> {
bytes: [u8; N],
}
pub struct Slot<T> {
ptr: *mut u8,
_marker: PhantomData<T>,
}
impl<T> Slot<T> {
#[inline]
pub unsafe fn clone_ptr(&self) -> Self {
Slot {
ptr: self.ptr,
_marker: PhantomData,
}
}
#[inline]
pub fn as_ptr(&self) -> *mut u8 {
self.ptr
}
#[inline]
pub fn into_raw(self) -> *mut u8 {
let ptr = self.ptr;
core::mem::forget(self);
ptr
}
#[inline]
pub unsafe fn from_raw(ptr: *mut u8) -> Self {
Slot {
ptr,
_marker: PhantomData,
}
}
#[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> core::ops::Deref for Slot<T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
unsafe { &*self.ptr.cast::<T>() }
}
}
impl<T> core::ops::DerefMut for Slot<T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.ptr.cast::<T>() }
}
}
impl<T> core::convert::AsRef<T> for Slot<T> {
#[inline]
fn as_ref(&self) -> &T {
self
}
}
impl<T> core::convert::AsMut<T> for Slot<T> {
#[inline]
fn as_mut(&mut self) -> &mut T {
self
}
}
impl<T> core::borrow::Borrow<T> for Slot<T> {
#[inline]
fn borrow(&self) -> &T {
self
}
}
impl<T> core::borrow::BorrowMut<T> for Slot<T> {
#[inline]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for Slot<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("byte::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!(
"byte::Slot<{}> dropped without being freed — call slab.free(ptr) or slab.take(ptr)",
core::any::type_name::<T>()
);
}
}
pub struct ByteClaim<'a> {
ptr: *mut u8,
slab_ptr: *const u8,
free: unsafe fn(*const u8, *mut u8, usize),
chunk_idx: usize,
slot_size: usize,
_borrow: core::marker::PhantomData<&'a ()>,
}
impl ByteClaim<'_> {
pub(crate) unsafe fn from_raw_parts(
ptr: *mut u8,
slab_ptr: *const u8,
free: unsafe fn(*const u8, *mut u8, usize),
chunk_idx: usize,
slot_size: usize,
) -> Self {
Self {
ptr,
slab_ptr,
free,
chunk_idx,
slot_size,
_borrow: core::marker::PhantomData,
}
}
#[inline]
pub fn write<T>(self, value: T) -> Slot<T> {
validate_type_dynamic::<T>(self.slot_size);
unsafe { core::ptr::write(self.ptr.cast::<T>(), value) };
let ptr = self.ptr;
core::mem::forget(self);
Slot {
ptr,
_marker: core::marker::PhantomData,
}
}
#[inline]
pub unsafe fn write_raw(self, src: *const u8, size: usize) -> *mut u8 {
assert!(
size <= self.slot_size,
"write_raw size ({size}) exceeds slot size ({})",
self.slot_size
);
unsafe { core::ptr::copy_nonoverlapping(src, self.ptr, size) };
let ptr = self.ptr;
core::mem::forget(self);
ptr
}
#[inline]
pub fn as_ptr(&self) -> *mut u8 {
self.ptr
}
#[inline]
pub fn slot_size(&self) -> usize {
self.slot_size
}
#[inline]
pub fn chunk_idx(&self) -> usize {
self.chunk_idx
}
}
impl Drop for ByteClaim<'_> {
fn drop(&mut self) {
unsafe { (self.free)(self.slab_ptr, self.ptr, self.chunk_idx) };
}
}
impl core::fmt::Debug for ByteClaim<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ByteClaim")
.field("ptr", &self.ptr)
.field("slot_size", &self.slot_size)
.finish()
}
}
#[inline]
fn validate_type_dynamic<T>(slot_size: usize) {
assert!(
core::mem::size_of::<T>() <= slot_size,
"type {} ({} bytes) exceeds byte slab slot size ({slot_size} bytes)",
core::any::type_name::<T>(),
core::mem::size_of::<T>(),
);
assert!(
core::mem::align_of::<T>() <= 8,
"type {} (align {}) exceeds byte slab alignment (8)",
core::any::type_name::<T>(),
core::mem::align_of::<T>(),
);
}
#[inline]
fn validate_type<T, const N: usize>() {
assert!(
core::mem::size_of::<T>() <= N,
"type {} ({} bytes) exceeds byte slab slot size ({N} bytes)",
core::any::type_name::<T>(),
core::mem::size_of::<T>(),
);
assert!(
core::mem::align_of::<T>() <= 8,
"type {} (align {}) exceeds byte slab alignment (8)",
core::any::type_name::<T>(),
core::mem::align_of::<T>(),
);
}
pub mod bounded;
pub mod unbounded;