placid 0.2.1

Separated ownership and in-place construction in Rust
Documentation
use core::{
    cell::{Cell, UnsafeCell},
    marker::PhantomPinned,
    mem::{self, ManuallyDrop},
};

use crate::{init::*, pin::DropSlot, uninit::Uninit};

macro_rules! derive_value_wrapper {
    ($($ty:ident: ($pin:ident, $unpin:ident)),* $(,)?) => {$(
        #[doc(hidden)]
        pub struct $unpin<'a, T: ?Sized, const C: bool> {
            uninit: Uninit<'a, $ty<T>>,
        }

        impl<'a, T: ?Sized, const C: bool> $unpin<'a, T, C> {
            #[doc(hidden)]
            #[inline]
            unsafe fn __drop_init(&mut self) {
                let base = self.uninit.as_mut_ptr();
                if C {
                    unsafe { base.drop_in_place() };
                }
            }
            #[doc(hidden)]
            #[inline]
            fn __err<E>(self, err: E) -> InitError<'a, $ty<T>, E> {
                let mut this = mem::ManuallyDrop::new(self);
                unsafe { this.__drop_init() };
                InitError {
                    error: err,
                    place: unsafe { core::ptr::read(&this.uninit) },
                }
            }
        }

        impl<'a, T: ?Sized, const C: bool> Drop for $unpin<'a, T, C> {
            #[inline]
            fn drop(&mut self) {
                unsafe { self.__drop_init() };
            }
        }

        impl<'a, T: ?Sized> $unpin<'a, T, false> {
            #[inline]
            pub fn __next<A, E, M>(
                mut self,
                init: A,
            ) -> Result<$unpin<'a, T, true>, InitError<'a, $ty<T>, E>>
            where
                A: IntoInit<T, M, Error = E>,
            {
                let init = init.into_init();
                let field_place = unsafe { Uninit::from_raw(self.uninit.as_mut_ptr() as *mut T) };
                match init.init(field_place) {
                    Ok(own) => {
                        mem::forget(own);
                        Ok(
                            unsafe {
                                mem::transmute::<
                                    $unpin<'a, T, false>,
                                    $unpin<'a, T, true>,
                                >(self)
                            },
                        )
                    }
                    Err(err) => Err(self.__err(err.error)),
                }
            }
        }

        impl<'a, T: ?Sized> $unpin<'a, T, true> {
            #[inline]
            #[doc(hidden)]
            pub fn __build(self) -> Own<'a, $ty<T>> {
                let this = mem::ManuallyDrop::new(self);
                unsafe {
                    let uninit = core::ptr::read(&this.uninit);
                    uninit.assume_init()
                }
            }
        }

        impl<'a, T: ?Sized + 'a> StructuralInit<'a> for $ty<T> {
            type __BuilderInit = $unpin<'a, T, false>;
            #[inline]
            fn __builder_init(uninit: Uninit<'a, $ty<T>>) -> $unpin<'a, T, false> {
                $unpin { uninit }
            }
        }

        #[doc(hidden)]
        pub struct $pin<'a, 'b, T: ?Sized, const C: bool> {
            uninit: Uninit<'a, $ty<T>>,
            slot: DropSlot<'a, 'b, $ty<T>>,
        }

        impl<'a, 'b, T: ?Sized, const C: bool> $pin<'a, 'b, T, C> {
            #[doc(hidden)]
            #[inline]
            unsafe fn __drop_init(&mut self) {
                let base = self.uninit.as_mut_ptr();
                if C {
                    unsafe { base.drop_in_place() };
                }
            }
            #[doc(hidden)]
            #[inline]
            fn __err<E>(self, err: E) -> InitPinError<'a, 'b, $ty<T>, E> {
                let mut this = mem::ManuallyDrop::new(self);
                unsafe { this.__drop_init() };
                InitPinError {
                    error: err,
                    place: unsafe { core::ptr::read(&this.uninit) },
                    slot: unsafe { core::ptr::read(&this.slot) },
                }
            }
        }

        impl<'a, 'b, T: ?Sized, const C: bool> Drop for $pin<'a, 'b, T, C> {
            #[inline]
            fn drop(&mut self) {
                unsafe { self.__drop_init() };
            }
        }

        impl<'a, 'b, T: ?Sized> $pin<'a, 'b, T, false> {
            #[inline]
            pub fn __next<A, E, M>(
                mut self,
                init: A,
            ) -> Result<$pin<'a, 'b, T, true>, InitPinError<'a, 'b, $ty<T>, E>>
            where
                A: IntoInitPin<T, M, Error = E>,
            {
                let init = init.into_init();
                let mut slot = mem::ManuallyDrop::new(crate::pin::DroppingSlot::new());
                let slot_ref = unsafe {
                    mem::transmute::<DropSlot<'_, '_, T>, DropSlot<'a, 'b, T>>(DropSlot::new_unchecked(
                        &mut slot,
                    ))
                };
                let field_place = unsafe { Uninit::from_raw(self.uninit.as_mut_ptr() as *mut T) };
                match init.init_pin(field_place, slot_ref) {
                    Ok(own) => {
                        mem::forget(own);
                        Ok(unsafe {
                            let this = ManuallyDrop::new(self);
                            let uninit = core::ptr::read(&this.uninit);
                            let slot = core::ptr::read(&this.slot);
                            $pin { uninit, slot }
                        })
                    }
                    Err(err) => Err(self.__err(err.error)),
                }
            }
        }

        impl<'a, 'b, T: ?Sized> $pin<'a, 'b, T, true> {
            #[inline]
            #[doc(hidden)]
            pub fn __build(self) -> POwn<'b, $ty<T>> {
                let this = mem::ManuallyDrop::new(self);
                unsafe {
                    let uninit = core::ptr::read(&this.uninit);
                    let slot = core::ptr::read(&this.slot);
                    uninit.assume_init_pin(slot)
                }
            }
        }

        impl<'b, T: 'b + ?Sized> StructuralInitPin<'b> for $ty<T> {
            type __BuilderInitPin<'a: 'b>
                = $pin<'a, 'b, T, false>
            where
                Self: 'a;

            #[inline]
            fn __builder_init_pin<'a>(
                uninit: Uninit<'a, $ty<T>>,
                slot: DropSlot<'a, 'b, $ty<T>>,
            ) -> $pin<'a, 'b, T, false>
            where
                Self: 'a,
            {
                $pin { uninit, slot }
            }
        }
    )*};
}

derive_value_wrapper! {
    Cell: (InitPinCell, InitCell),
    UnsafeCell: (InitPinUnsafeCell, InitUnsafeCell),
    ManuallyDrop: (InitPinManuallyDrop, InitManuallyDrop),
}

#[doc(hidden)]
pub struct InitPhantomPinned<'a> {
    uninit: Uninit<'a, PhantomPinned>,
}

impl<'a> InitPhantomPinned<'a> {
    #[inline]
    #[doc(hidden)]
    pub fn __build(self) -> Own<'a, PhantomPinned> {
        unsafe { self.uninit.assume_init() }
    }
}

impl<'a> StructuralInit<'a> for PhantomPinned {
    type __BuilderInit = InitPhantomPinned<'a>;
    #[inline]
    fn __builder_init(uninit: Uninit<'a, PhantomPinned>) -> InitPhantomPinned<'a> {
        InitPhantomPinned { uninit }
    }
}

#[doc(hidden)]
pub struct InitPinPhantomPinned<'a, 'b> {
    uninit: Uninit<'a, PhantomPinned>,
    slot: DropSlot<'a, 'b, PhantomPinned>,
}

impl<'a, 'b> InitPinPhantomPinned<'a, 'b> {
    #[inline]
    #[doc(hidden)]
    pub fn __build(self) -> POwn<'b, PhantomPinned> {
        unsafe { self.uninit.assume_init_pin(self.slot) }
    }
}

impl<'b> StructuralInitPin<'b> for PhantomPinned {
    type __BuilderInitPin<'a: 'b>
        = InitPinPhantomPinned<'a, 'b>
    where
        Self: 'a;

    #[inline]
    fn __builder_init_pin<'a>(
        uninit: Uninit<'a, PhantomPinned>,
        slot: DropSlot<'a, 'b, PhantomPinned>,
    ) -> InitPinPhantomPinned<'a, 'b>
    where
        Self: 'a,
    {
        InitPinPhantomPinned { uninit, slot }
    }
}