#[cfg(feature = "unsize")]
use core::marker::Unsize;
#[cfg(feature = "unsize")]
use core::ptr::DynMetadata;
use core::ptr::{NonNull, Pointee};
use core::{fmt, ptr};
use crate::error;
use crate::error::StorageError;
use crate::handles::Handle;
macro_rules! create_drop {
($create:ident, $create_range:ident, $create_dyn:ident, $drop:ident; $allocate:ident, $deallocate:ident) => {
fn $create<T: Pointee>(
&mut self,
value: T,
) -> core::result::Result<Self::Handle<T>, (StorageError, T)> {
let handle = match self.$allocate(()) {
Ok(handle) => handle,
Err(e) => return Err((e, value)),
};
let pointer = unsafe { self.get(handle) };
unsafe { ptr::write(pointer.as_ptr(), value) };
Ok(handle)
}
#[cfg(feature = "unsize")]
fn $create_range<U, T: Unsize<[U]>>(
&mut self,
value: T,
) -> error::Result<Self::Handle<[U]>> {
let meta = ptr::metadata(&value as &[U]);
let handle = self.$allocate(meta)?;
let pointer: NonNull<[U]> = unsafe { self.get(handle) };
unsafe { ptr::write(pointer.as_ptr().cast(), value) };
Ok(handle)
}
#[cfg(feature = "unsize")]
fn $create_dyn<Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>, T: Unsize<Dyn>>(
&mut self,
value: T,
) -> error::Result<Self::Handle<Dyn>> {
let meta = ptr::metadata(&value as &Dyn);
let handle = self.$allocate(meta)?;
let pointer: NonNull<Dyn> = unsafe { self.get(handle) };
unsafe { ptr::write(pointer.as_ptr().cast(), value) };
Ok(handle)
}
unsafe fn $drop<T: ?Sized + Pointee>(&mut self, handle: Self::Handle<T>) {
let element = unsafe { self.get(handle) };
unsafe { ptr::drop_in_place(element.as_ptr()) };
unsafe { self.$deallocate(handle) };
}
};
}
pub unsafe trait StorageSafe: Sized + Copy + fmt::Debug {}
unsafe impl StorageSafe for u8 {}
unsafe impl StorageSafe for u16 {}
unsafe impl StorageSafe for u32 {}
unsafe impl StorageSafe for u64 {}
unsafe impl StorageSafe for u128 {}
unsafe impl StorageSafe for usize {}
unsafe impl<T: StorageSafe, const N: usize> StorageSafe for [T; N] {}
pub unsafe trait Storage {
type Handle<T: ?Sized>: Copy + PartialEq + Handle<Target = T>;
unsafe fn get<T: ?Sized>(&self, handle: Self::Handle<T>) -> NonNull<T>;
fn from_raw_parts<T: ?Sized + Pointee>(
handle: Self::Handle<()>,
meta: T::Metadata,
) -> Self::Handle<T>;
fn cast<T: ?Sized + Pointee, U>(handle: Self::Handle<T>) -> Self::Handle<U>;
fn cast_unsized<T: ?Sized + Pointee, U: ?Sized + Pointee<Metadata = T::Metadata>>(
handle: Self::Handle<T>,
) -> Self::Handle<U>;
#[cfg(feature = "unsize")]
fn coerce<T: ?Sized + Pointee + Unsize<U>, U: ?Sized + Pointee>(
handle: Self::Handle<T>,
) -> Self::Handle<U>;
fn allocate_single<T: ?Sized + Pointee>(
&mut self,
meta: T::Metadata,
) -> error::Result<Self::Handle<T>>;
unsafe fn deallocate_single<T: ?Sized>(&mut self, handle: Self::Handle<T>);
#[allow(unused_variables)]
unsafe fn try_grow<T>(
&mut self,
handle: Self::Handle<[T]>,
capacity: usize,
) -> error::Result<Self::Handle<[T]>> {
Err(StorageError::Unimplemented)
}
#[allow(unused_variables)]
unsafe fn try_shrink<T>(
&mut self,
handle: Self::Handle<[T]>,
capacity: usize,
) -> error::Result<Self::Handle<[T]>> {
Err(StorageError::Unimplemented)
}
create_drop!(
create_single, create_single_range, create_single_dyn, drop_single;
allocate_single, deallocate_single
);
}
unsafe impl<S: Storage> Storage for &mut S {
type Handle<T: ?Sized> = S::Handle<T>;
unsafe fn get<T: ?Sized>(&self, handle: Self::Handle<T>) -> NonNull<T> {
unsafe { S::get(self, handle) }
}
fn from_raw_parts<T: ?Sized + Pointee>(
handle: Self::Handle<()>,
meta: T::Metadata,
) -> Self::Handle<T> {
S::from_raw_parts(handle, meta)
}
fn cast<T: ?Sized + Pointee, U>(handle: Self::Handle<T>) -> Self::Handle<U> {
S::cast(handle)
}
fn cast_unsized<T: ?Sized + Pointee, U: ?Sized + Pointee<Metadata = T::Metadata>>(
handle: Self::Handle<T>,
) -> Self::Handle<U> {
S::cast_unsized(handle)
}
#[cfg(feature = "unsize")]
fn coerce<T: ?Sized + Pointee + Unsize<U>, U: ?Sized + Pointee>(
handle: Self::Handle<T>,
) -> Self::Handle<U> {
S::coerce(handle)
}
fn allocate_single<T: ?Sized + Pointee>(
&mut self,
meta: T::Metadata,
) -> error::Result<Self::Handle<T>> {
S::allocate_single(self, meta)
}
unsafe fn deallocate_single<T: ?Sized>(&mut self, handle: Self::Handle<T>) {
unsafe { S::deallocate_single(self, handle) }
}
unsafe fn try_grow<T>(
&mut self,
handle: Self::Handle<[T]>,
capacity: usize,
) -> error::Result<Self::Handle<[T]>> {
unsafe { S::try_grow(self, handle, capacity) }
}
unsafe fn try_shrink<T>(
&mut self,
handle: Self::Handle<[T]>,
capacity: usize,
) -> error::Result<Self::Handle<[T]>> {
unsafe { S::try_shrink(self, handle, capacity) }
}
}
unsafe impl<S> MultiItemStorage for &mut S
where
S: MultiItemStorage,
{
fn allocate<T: ?Sized + Pointee>(
&mut self,
meta: T::Metadata,
) -> error::Result<Self::Handle<T>> {
S::allocate(self, meta)
}
unsafe fn deallocate<T: ?Sized + Pointee>(&mut self, handle: Self::Handle<T>) {
unsafe { S::deallocate(self, handle) }
}
}
impl<S> ExactSizeStorage for &mut S
where
S: ExactSizeStorage,
{
fn will_fit<T: ?Sized + Pointee>(&self, meta: T::Metadata) -> bool {
S::will_fit::<T>(self, meta)
}
fn max_range<T>(&self) -> usize {
S::max_range::<T>(self)
}
}
unsafe impl<S> LeaksafeStorage for &mut S where S: LeaksafeStorage {}
pub unsafe trait MultiItemStorage: Storage {
fn allocate<T: ?Sized + Pointee>(
&mut self,
meta: T::Metadata,
) -> error::Result<Self::Handle<T>>;
unsafe fn deallocate<T: ?Sized + Pointee>(&mut self, handle: Self::Handle<T>);
create_drop!(
create, create_range, create_dyn, drop;
allocate, deallocate
);
}
pub trait ExactSizeStorage: Storage {
fn will_fit<T: ?Sized + Pointee>(&self, meta: T::Metadata) -> bool;
fn max_range<T>(&self) -> usize;
}
pub unsafe trait ClonesafeStorage: Storage + Clone {}
pub unsafe trait LeaksafeStorage: Storage {}
pub unsafe trait FromLeakedStorage: LeaksafeStorage + ClonesafeStorage {
unsafe fn unleak_ptr<T: ?Sized>(&self, leaked: *mut T) -> Self::Handle<T>;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::inline::SingleInline;
type Store = SingleInline<[usize; 4]>;
#[test]
fn create_single() {
let mut storage = Store::default();
let handle = storage.create_single(1.0f32).unwrap();
unsafe { storage.drop_single(handle) };
}
#[test]
fn create_single_range() {
let mut storage = Store::default();
let handle = storage.create_single_range::<u8, _>([1, 2, 3, 4]).unwrap();
unsafe { storage.drop_single(handle) };
}
#[test]
fn create_single_dyn() {
let mut storage = Store::default();
let handle = storage
.create_single_dyn::<dyn fmt::Debug, _>("Hello!")
.unwrap();
unsafe { storage.drop_single(handle) };
}
}