use crate::Initializer;
use super::{Layout, VarLen};
use core::marker::PhantomData;
use core::pin::Pin;
use core::ptr::NonNull;
pub struct Owned<'storage, T: VarLen>(NonNull<T>, PhantomData<&'storage [u8]>);
#[allow(rustdoc::missing_doc_code_examples)]
impl<'storage, T: VarLen> Owned<'storage, T> {
pub unsafe fn from_raw(raw: NonNull<T>) -> Self {
Owned(raw, PhantomData)
}
pub unsafe fn into_raw(self) -> NonNull<T> {
let result = self.0;
core::mem::forget(self);
result
}
pub fn as_mut(&mut self) -> Pin<&mut T> {
unsafe { Pin::new_unchecked(self.0.as_mut()) }
}
pub fn leak(self) -> Pin<&'storage mut T> {
let Owned(mut ptr, _) = self;
unsafe { Pin::new_unchecked(ptr.as_mut()) }
}
#[cfg(feature = "bumpalo")]
#[inline]
pub fn new_in(init: impl Initializer<T>, bump: &'storage bumpalo::Bump) -> Self {
use core::alloc;
let layout = init.calculate_layout_cautious().unwrap();
let ptr = bump
.alloc_layout(alloc::Layout::from_size_align(layout.size(), T::ALIGN).unwrap())
.cast::<T>();
unsafe {
init.initialize(ptr, layout);
}
Owned(ptr, PhantomData)
}
}
impl<T: VarLen> Drop for Owned<'_, T> {
fn drop(&mut self) {
unsafe {
let layout = T::calculate_layout(&*self);
T::vdrop(self.as_mut(), layout);
}
}
}
impl<T: VarLen> core::ops::Deref for Owned<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.0.as_ref() }
}
}
unsafe impl<T: VarLen> Initializer<T> for Owned<'_, T> {
unsafe fn initialize(self, dst: NonNull<T>, layout: T::Layout) {
core::ptr::copy_nonoverlapping(self.0.as_ptr(), dst.as_ptr(), layout.size());
core::mem::forget(self);
}
#[inline]
fn calculate_layout_cautious(&self) -> Option<T::Layout> {
Some(T::calculate_layout(&*self))
}
}