use ::core::alloc::Layout;
use ::core::mem;
use ::core::ptr::{self, NonNull};
pub use allocator_api2::alloc::{AllocError, Allocator};
#[cfg(feature = "alloc")]
pub use allocator_api2::{alloc::Global, boxed::Box, unsize_box};
pub trait TryCloneIn: Sized {
type Target<A: Allocator + Clone>;
fn try_clone_in<A: Allocator + Clone>(&self, alloc: A) -> Result<Self::Target<A>, AllocError>;
}
pub fn allocate<T, A>(value: T, alloc: &A) -> Result<NonNull<T>, AllocError>
where
A: Allocator,
{
let layout = Layout::for_value(&value);
let ptr: NonNull<T> = alloc.allocate(layout)?.cast();
unsafe { ptr.cast::<mem::MaybeUninit<T>>().as_mut().write(value) };
Ok(ptr)
}
#[inline(always)]
pub(crate) const fn dangling_for_layout(layout: &Layout) -> NonNull<u8> {
unsafe {
let ptr = ptr::null_mut::<u8>().byte_add(layout.align());
NonNull::new_unchecked(ptr)
}
}
#[cfg(feature = "alloc")]
mod impls {
use allocator_api2::boxed::Box;
use super::*;
impl<T, OA> TryCloneIn for Box<T, OA>
where
T: TryCloneIn,
OA: Allocator,
{
type Target<A: Allocator + Clone> = Box<<T as TryCloneIn>::Target<A>, A>;
fn try_clone_in<A: Allocator + Clone>(
&self,
alloc: A,
) -> Result<Self::Target<A>, AllocError> {
let x = self.as_ref().try_clone_in(alloc.clone())?;
Box::try_new_in(x, alloc)
}
}
}