#[cfg(feature = "unstable_out")]
pub mod out {
use crate::Own;
use core::mem::{MaybeUninit, transmute_prefix};
use core::ptr::NonNull;
#[repr(transparent)]
pub struct Out<'a, T> {
inner: &'a mut MaybeUninit<T>
}
const impl<'a, T> Out<'a, T> {
fn write(self, val: Own<T>) -> &'a mut T {
let src: NonNull<T> = unsafe { transmute_prefix(val) };
let dst = unsafe { NonNull::new_unchecked(self.inner.as_mut_ptr()) };
unsafe { src.copy_to_nonoverlapping(dst, 1); }
unsafe { transmute_prefix(self) }
}
unsafe fn assume_initialized(self) -> &'a mut T {
unsafe { transmute_prefix(self) }
}
}
impl<'a, T> Drop for Out<'a, T> {
#[rustc_nounwind]
fn drop(&mut self) {
panic!("Out reference was dropped without initialization!")
}
}
#[macro_export]
macro_rules! let_out {
(let out $p:pat_param) => {{
super let __OUT_UNINIT = ::core::mem::MaybeUninit::uninit();
&mut __OUT_UNINIT
}};
}
pub trait Relocate {
fn relocate(self: Own<Self>, dst: Out<Self>)
where
Self: Sized;
}
impl<T> Relocate for T {
#[inline(always)]
default fn relocate(self: Own<Self>, dst: Out<Self>) {
dst.write(self);
}
}
}
#[cfg(feature = "unstable_dyn_example")]
pub mod dyn_example {
use crate::Own;
use crate::traits::DerefMove;
use core::marker::PhantomData;
use core::mem::transmute_prefix;
use core::ptr::NonNull;
pub struct Output(usize);
pub trait X {
fn do_stuff(self) -> Output;
}
struct DynXMeta {
size: usize,
do_stuff: unsafe fn(NonNull<()>) -> Output,
}
const fn dyn_x_meta<'a, T: X + 'a>() -> &'a DynXMeta {
&const {
DynXMeta {
size: size_of::<T>(),
do_stuff: unsafe {
transmute_prefix(do_stuff_through_own_ref::<T> as fn(Own<'a, T>) -> Output)
}
}
}
}
fn do_stuff_through_own_ref<T: X>(this: Own<T>) -> Output {
this.deref_move().do_stuff()
}
pub struct OwnDynXPointee<'a> {
meta: &'a DynXMeta,
ptr: NonNull<()>,
phantom: PhantomData<Own<'a, ()>>
}
impl<'a> X for OwnDynXPointee<'a> {
fn do_stuff(self) -> Output {
unsafe { (self.meta.do_stuff)(self.ptr) }
}
}
impl<'a> OwnDynXPointee<'a> {
pub const fn of<T: X>(ptr: Own<'a, T>) -> Self {
Self {
meta: const { dyn_x_meta::<T>() },
ptr: unsafe { transmute_prefix(ptr) },
phantom: PhantomData
}
}
}
}