use core::ptr::NonNull;
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
macro_rules! impl_copy_clone {
( $($name:ident),* ) => { $( impl<T> Copy for $name<T> { }
impl<T> Clone for $name<T> {
fn clone(&self) -> Self {
*self
}
}
)* };
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl_copy_clone!(BoxedStorage, BoxedSliceStorage);
impl_copy_clone!(StaticStorage, StaticSliceStorage);
pub unsafe trait FixedStorage<T> {
fn as_ptr(&self) -> NonNull<T>;
unsafe fn as_ref(&self) -> &T {
unsafe { self.as_ptr().as_ref() }
}
unsafe fn deallocate(&self);
}
pub unsafe trait FixedStorageMultiple<T>: FixedStorage<T> {
fn capacity(&self) -> usize;
#[inline]
fn slice(&self) -> &[T] {
unsafe {
core::slice::from_raw_parts(
self.as_ptr().as_ptr(),
self.capacity(),
)
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
use alloc::{boxed::Box, vec::Vec};
#[cfg(any(feature = "std", feature = "alloc"))]
#[repr(transparent)]
pub struct BoxedStorage<T> {
ptr: NonNull<T>,
}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T: Send> Send for BoxedStorage<T> {}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T: Sync> Sync for BoxedStorage<T> {}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> BoxedStorage<T> {
#[inline]
pub fn new(value: T) -> Self {
Self::from_boxed(Box::new(value))
}
#[inline]
pub fn from_boxed(boxed: Box<T>) -> Self {
let ptr = Box::into_raw(boxed);
Self {
ptr: unsafe { NonNull::new_unchecked(ptr) },
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T> FixedStorage<T> for BoxedStorage<T> {
fn as_ptr(&self) -> NonNull<T> {
self.ptr
}
unsafe fn deallocate(&self) {
unsafe {
let _ = Box::from_raw(self.ptr.as_ptr());
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub struct BoxedSliceStorage<T> {
ptr: NonNull<T>,
capacity: usize,
}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T: Send> Send for BoxedSliceStorage<T> {}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T: Sync> Sync for BoxedSliceStorage<T> {}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T> BoxedSliceStorage<T> {
pub fn from_boxed_slice(boxed: Box<[T]>) -> Self {
let capacity = boxed.len();
let ptr = Box::into_raw(boxed) as *mut T;
Self {
ptr: unsafe { NonNull::new_unchecked(ptr) },
capacity,
}
}
pub fn with_capacity_and_init<F>(capacity: usize, mut init: F) -> Self
where
F: FnMut() -> T,
{
let mut v = Vec::with_capacity(capacity);
for _ in 0..capacity {
v.push(init());
}
Self::from_boxed_slice(v.into_boxed_slice())
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T> FixedStorage<T> for BoxedSliceStorage<T> {
fn as_ptr(&self) -> NonNull<T> {
self.ptr
}
unsafe fn deallocate(&self) {
unsafe {
let slice = core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.capacity);
let _ = Box::from_raw(slice as *mut [T]);
}
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
unsafe impl<T> FixedStorageMultiple<T> for BoxedSliceStorage<T> {
fn capacity(&self) -> usize {
self.capacity
}
}
#[repr(transparent)]
pub struct StaticStorage<T> {
ptr: NonNull<T>,
phantom: core::marker::PhantomData<T>,
}
unsafe impl<T: Send> Send for StaticStorage<T> {}
unsafe impl<T: Sync> Sync for StaticStorage<T> {}
impl<T> StaticStorage<T> {
pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
Self {
ptr,
phantom: core::marker::PhantomData,
}
}
}
unsafe impl<T> FixedStorage<T> for StaticStorage<T> {
fn as_ptr(&self) -> NonNull<T> {
self.ptr
}
unsafe fn deallocate(&self) {
}
}
pub struct StaticSliceStorage<T> {
ptr: NonNull<T>,
capacity: usize,
phantom: core::marker::PhantomData<T>,
}
unsafe impl<T: Send> Send for StaticSliceStorage<T> {}
unsafe impl<T: Sync> Sync for StaticSliceStorage<T> {}
impl<T> StaticSliceStorage<T> {
pub unsafe fn from_static(slice: &'static mut [T]) -> Self {
Self {
ptr: unsafe { NonNull::new_unchecked(slice.as_mut_ptr()) },
capacity: slice.len(),
phantom: core::marker::PhantomData,
}
}
pub unsafe fn from_raw(ptr: NonNull<T>, capacity: usize) -> Self {
Self {
ptr,
capacity,
phantom: core::marker::PhantomData,
}
}
}
unsafe impl<T> FixedStorage<T> for StaticSliceStorage<T> {
fn as_ptr(&self) -> NonNull<T> {
self.ptr
}
unsafe fn deallocate(&self) {
}
}
unsafe impl<T> FixedStorageMultiple<T> for StaticSliceStorage<T> {
fn capacity(&self) -> usize {
self.capacity
}
}