use core::convert::Infallible;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::pin::Pin;
#[cfg(doc)]
use {crate::new, core::ops::DerefMut};
use alloc::{boxed::Box, rc::Rc, sync::Arc};
mod copy_new;
mod factories;
mod move_new;
mod impls;
pub use copy_new::*;
pub use factories::*;
pub use move_new::*;
#[must_use = "`New`s do nothing until emplaced into storage"]
pub unsafe trait New: Sized {
type Output;
unsafe fn new(self, this: Pin<&mut MaybeUninit<Self::Output>>);
fn with<F>(self, post: F) -> With<Self, F>
where
F: FnOnce(Pin<&mut Self::Output>),
{
With(self, post)
}
}
#[must_use = "`New`s do nothing until emplaced into storage"]
pub unsafe trait TryNew: Sized {
type Output;
type Error;
unsafe fn try_new(
self,
this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error>;
fn with<F>(self, post: F) -> TryWith<Self, F> {
TryWith(self, post)
}
}
unsafe impl<N: New> TryNew for N {
type Output = N::Output;
type Error = Infallible;
unsafe fn try_new(
self,
this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error> {
self.new(this);
Ok(())
}
}
pub trait Emplace<T>: Sized + Deref {
type Output: Deref<Target = Self::Target>;
fn emplace<N: New<Output = T>>(n: N) -> Self::Output {
match Self::try_emplace(n) {
Ok(x) => x,
Err(e) => match e {},
}
}
fn try_emplace<N: TryNew<Output = T>>(n: N)
-> Result<Self::Output, N::Error>;
}
impl<T> Emplace<T> for Box<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let mut uninit = Box::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *uninit);
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Box::from_raw(
Box::into_raw(uninit).cast::<T>(),
)))
}
}
}
impl<T> Emplace<T> for Rc<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let uninit = Rc::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *(Rc::as_ptr(&uninit) as *mut _));
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Rc::from_raw(
Rc::into_raw(uninit).cast::<T>(),
)))
}
}
}
impl<T> Emplace<T> for Arc<T> {
type Output = Pin<Self>;
fn try_emplace<N: TryNew<Output = T>>(
n: N,
) -> Result<Self::Output, N::Error> {
let uninit = Arc::new(MaybeUninit::<T>::uninit());
unsafe {
let pinned = Pin::new_unchecked(&mut *(Arc::as_ptr(&uninit) as *mut _));
n.try_new(pinned)?;
Ok(Pin::new_unchecked(Arc::from_raw(
Arc::into_raw(uninit).cast::<T>(),
)))
}
}
}
#[doc(hidden)]
pub struct With<N, F>(N, F);
unsafe impl<N: New, F> New for With<N, F>
where
F: FnOnce(Pin<&mut N::Output>),
{
type Output = N::Output;
#[inline]
unsafe fn new(self, mut this: Pin<&mut MaybeUninit<Self::Output>>) {
self.0.new(this.as_mut());
let this = this.map_unchecked_mut(|x| x.assume_init_mut());
(self.1)(this)
}
}
#[doc(hidden)]
pub struct TryWith<N, F>(N, F);
unsafe impl<N: TryNew, F> TryNew for TryWith<N, F>
where
F: FnOnce(Pin<&mut N::Output>) -> Result<(), N::Error>,
{
type Output = N::Output;
type Error = N::Error;
#[inline]
unsafe fn try_new(
self,
mut this: Pin<&mut MaybeUninit<Self::Output>>,
) -> Result<(), Self::Error> {
self.0.try_new(this.as_mut())?;
let this = this.map_unchecked_mut(|x| x.assume_init_mut());
(self.1)(this)
}
}
pub trait Swap<Rhs = Self> {
fn swap_with(self: Pin<&mut Self>, src: Pin<&mut Rhs>);
}