use core::{
fmt,
mem::{self, MaybeUninit},
ops::{Deref, DerefMut},
ptr::NonNull,
slice,
};
use crate::{
init::{Init, InitPin, InitPinResult, InitResult, IntoInit, IntoInitPin},
owned::Own,
pin::{DropSlot, POwn},
place::{Place, PlaceRef, Uninitialized},
};
pub type Uninit<'a, T> = PlaceRef<'a, T, Uninitialized>;
#[macro_export]
#[allow_internal_unstable(super_let)]
macro_rules! uninit {
() => {{
super let mut place = ::core::mem::MaybeUninit::uninit();
$crate::uninit::Uninit::from_mut(&mut place)
}};
($ty:ty) => {{
super let mut place = ::core::mem::MaybeUninit::<$ty>::uninit();
$crate::uninit::Uninit::from_mut(&mut place)
}};
}
impl<'a, T> Deref for Uninit<'a, T> {
type Target = MaybeUninit<T>;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.inner.cast().as_ref() }
}
}
impl<'a, T> DerefMut for Uninit<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.inner.cast().as_mut() }
}
}
impl<'a, T> Deref for Uninit<'a, [T]> {
type Target = [MaybeUninit<T>];
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
let data = self.inner.as_ptr();
slice::from_raw_parts(data.cast(), data.len())
}
}
}
impl<'a, T> DerefMut for Uninit<'a, [T]> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
let data = self.inner.as_ptr();
slice::from_raw_parts_mut(data.cast(), data.len())
}
}
}
impl<'a> Deref for Uninit<'a, str> {
type Target = [MaybeUninit<u8>];
#[inline]
fn deref(&self) -> &Self::Target {
unsafe {
let (addr, len) = self.inner.as_ptr().to_raw_parts();
slice::from_raw_parts(addr.cast(), len)
}
}
}
impl<'a> DerefMut for Uninit<'a, str> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe {
let (addr, len) = self.inner.as_ptr().to_raw_parts();
slice::from_raw_parts_mut(addr.cast(), len)
}
}
}
impl<'a, T: ?Sized> Uninit<'a, T> {
#[inline]
pub const fn into_raw(self) -> *mut T {
let inner = self.inner;
mem::forget(self);
inner.as_ptr()
}
#[inline]
pub const unsafe fn from_raw(ptr: *mut T) -> Self {
let inner = unsafe { NonNull::new_unchecked(ptr) };
unsafe { Uninit::from_inner(inner) }
}
#[inline]
pub fn from_mut(place: &'a mut impl Place<T>) -> Self {
unsafe { Self::from_raw(place.as_mut_ptr()) }
}
#[inline]
pub const fn as_mut_ptr(&mut self) -> *mut T {
self.inner.as_ptr()
}
#[inline]
pub const unsafe fn assume_init(self) -> Own<'a, T> {
let inner = self.inner;
mem::forget(self);
unsafe { Own::from_inner(inner) }
}
#[inline]
pub unsafe fn assume_init_pin<'b>(self, slot: DropSlot<'a, 'b, T>) -> POwn<'b, T> {
let inner = self.inner;
mem::forget(self);
POwn::new(unsafe { Own::from_inner(inner) }, slot)
}
#[inline]
pub fn write<I, M>(self, init: I) -> Own<'a, T>
where
I: IntoInit<T, M, Error: fmt::Debug>,
{
self.try_write(init).unwrap()
}
#[inline]
pub fn try_write<I, M>(self, init: I) -> InitResult<'a, T, I::Error>
where
I: IntoInit<T, M>,
{
init.into_init().init(self)
}
#[inline]
pub fn write_pin<'b, I, M>(self, init: I, slot: DropSlot<'a, 'b, T>) -> POwn<'b, T>
where
I: IntoInitPin<T, M, Error: fmt::Debug>,
{
self.try_write_pin(init, slot).unwrap()
}
#[inline]
pub fn try_write_pin<'b, I, M>(
self,
init: I,
slot: DropSlot<'a, 'b, T>,
) -> InitPinResult<'a, 'b, T, I::Error>
where
I: IntoInitPin<T, M>,
{
init.into_init().init_pin(self, slot)
}
}
impl<'a, T: ?Sized> fmt::Debug for Uninit<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Uninit<{}>", core::any::type_name::<T>())
}
}