use core::convert::Infallible;
use core::{cell::UnsafeCell, mem::MaybeUninit};
pub use pinned_init::*;
pub fn into_init<F, T, E, I: Init<T, E>>(f: F) -> impl Init<T, E>
where
F: FnOnce() -> Result<I, E>,
{
unsafe { init_from_closure(move |slot| f()?.__init(slot)) }
}
pub trait IntoFallibleInit<T>: Init<T, Infallible> {
fn into_fallible<E>(self) -> impl Init<T, E> {
unsafe {
init_from_closure(move |slot| {
unwrap!(Self::__init(self, slot));
Ok(())
})
}
}
}
impl<T, I> IntoFallibleInit<T> for I where I: Init<T, Infallible> {}
pub trait UnsafeCellInit<T> {
fn init<I: Init<T>>(value: I) -> impl Init<Self>;
}
impl<T> UnsafeCellInit<T> for UnsafeCell<T> {
fn init<I: Init<T>>(value: I) -> impl Init<Self> {
unsafe {
init_from_closure::<_, Infallible>(move |slot: *mut Self| {
let slot: *mut T = slot as _;
unwrap!(value.__init(slot));
Ok(())
})
}
}
}
pub trait InitMaybeUninit<T> {
fn init_with<I: Init<T>>(&mut self, init: I) -> &mut T {
unwrap!(self.try_init_with(init))
}
fn try_init_with<I: Init<T, E>, E>(&mut self, init: I) -> Result<&mut T, E>;
fn init_zeroed(&mut self) -> &mut T
where
T: Zeroable,
{
self.init_with(pinned_init::zeroed())
}
}
impl<T> InitMaybeUninit<T> for MaybeUninit<T> {
fn try_init_with<I: Init<T, E>, E>(&mut self, init: I) -> Result<&mut T, E> {
unsafe {
Init::<T, E>::__init(init, self.as_mut_ptr())?;
Ok(self.assume_init_mut())
}
}
}
pub trait InitDefault: Sized {
fn init_default() -> impl Init<Self>;
}