49 lines
1.2 KiB
Rust
49 lines
1.2 KiB
Rust
use std::marker::PhantomData;
|
|
use std::mem::{self, MaybeUninit};
|
|
use std::ops::Deref;
|
|
use std::ptr::{addr_of, NonNull};
|
|
|
|
pub(crate) struct Owned<T, Init = T> {
|
|
ptr: NonNull<T>,
|
|
marker: PhantomData<NonNull<Init>>,
|
|
}
|
|
|
|
impl<T> Owned<T> {
|
|
pub fn new_uninit() -> Owned<MaybeUninit<T>, T> {
|
|
// FIXME: use Box::new_uninit when stable
|
|
let boxed = Box::new(MaybeUninit::<T>::uninit());
|
|
Owned {
|
|
ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) },
|
|
marker: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub unsafe fn assume_init(definitely_init: Owned<MaybeUninit<T>, T>) -> Owned<T> {
|
|
let ptr = definitely_init.ptr;
|
|
mem::forget(definitely_init);
|
|
Owned {
|
|
ptr: ptr.cast(),
|
|
marker: PhantomData,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
pub(crate) struct InitPtr<T> {
|
|
pub ptr: *mut T,
|
|
}
|
|
|
|
impl<T, Init> Deref for Owned<T, Init> {
|
|
type Target = InitPtr<Init>;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
unsafe { &*addr_of!(self.ptr).cast::<InitPtr<Init>>() }
|
|
}
|
|
}
|
|
|
|
impl<T, Init> Drop for Owned<T, Init> {
|
|
fn drop(&mut self) {
|
|
let _ = unsafe { Box::from_raw(self.ptr.as_ptr()) };
|
|
}
|
|
}
|