expiring_ref 0.7.1

A crate designed to implement a mechanism for owning values, via a destructively-moved equivalent to C++'s xvalues/`T&&`
Documentation
use crate::Own;
#[cfg(feature = "alloc")]
use alloc::{alloc::{Global, handle_alloc_error}, boxed::Box, vec::Vec, string::String};
#[cfg(feature = "alloc")]
use core::alloc::{Allocator, Layout};
use core::mem::{ManuallyDrop, MaybeDangling, MaybeUninit, transmute_prefix as transmute};
use core::ops::DerefMut;
use core::ptr;
use core::ptr::{NonNull, metadata};

pub const trait DerefMove: DerefMut<Target: Sized> {
	fn deref_move(self) -> Self::Target;
}

/// SAFETY: implementors must ensure `forget_contents` handles the MaybeDangling instance and ensure the inner value is NOT DROPPED.
pub const unsafe trait DerefOwn: DerefMut {
	// SAFETY: self MUST have a value and MUST have `forget_contents` called on it if the return of this function is moved from or dropped
	unsafe fn deref_own(self: &mut ManuallyDrop<Self>) -> Own<'_, Self::Target>;

	fn forget_contents(this: MaybeDangling<Self>);

	// SAFETY: `this` must not be used again.
	unsafe fn forget_contents_in_place(this: &mut ManuallyDrop<Self>) where Self: Sized {
		// SAFETY: `this` is not used again and MaybeDangling<T> is transparent around T
		unsafe {
			Self::forget_contents(transmute(ManuallyDrop::take(this)))
		}
	}
}
/// Values which may take a value and put it into an allocation.
pub trait Take<T: ?Sized> {
	/// Move the value into a new allocation.
	fn take(val: Own<T>) -> Self;
}

#[cfg(feature = "alloc")]
/// Values which may take a value and put it into an allocation, given a specified allocator.
pub trait TakeIn<T: ?Sized, A: Allocator> {
	/// Move the value into a new allocation given the specified allocator.
	fn take_in(val: Own<T>, alloc: A) -> Self;
}

impl<T: Sized> Take<T> for T {
	#[inline(always)]
	fn take(val: Own<T>) -> Self {
		val.deref_move()
	}
}

#[cfg(feature = "alloc")]
impl<T: ?Sized> Take<T> for Box<T> {
	#[inline(always)]
	fn take(val: Own<T>) -> Self {
		Self::take_in(val, Global)
	}
}

#[cfg(feature = "alloc")]
impl<T: ?Sized, A: Allocator> TakeIn<T, A> for Box<T, A> {
	#[inline(always)]
	fn take_in(val: Own<T>, alloc: A) -> Self {
		let val = MaybeDangling::new(val);
		let borrow = &**val.as_ref();
		let meta = metadata(borrow);
		let layout = Layout::for_value(borrow);
		let this_ptr = match alloc.allocate(layout) {
			Ok(m) => NonNull::<T>::from_raw_parts(m.as_non_null_ptr(), meta),
			Err(_) => handle_alloc_error(layout),
		};
		// SAFETY: The inner value is not moved nor dropped after this read
		unsafe { ptr::copy_nonoverlapping((borrow as *const T).cast::<u8>(), this_ptr.cast().as_ptr(), layout.size()); }

		DerefOwn::forget_contents(val);
		// SAFETY: `this` has been inhabited with a value
		unsafe { Box::from_raw_in(this_ptr.as_ptr(), alloc) }
	}
}

#[cfg(feature = "alloc")]
impl<T: Sized> Take<[T]> for Vec<T> {
	#[inline(always)]
	fn take(val: Own<[T]>) -> Self {
		let val = MaybeDangling::new(val);
		let borrow = &**val.as_ref();
		let len = borrow.len();
		let mut this: Vec<MaybeUninit<T>> = Box::new_uninit_slice(len).into_vec();
		let this_ptr = this[0].as_mut_ptr();
		// SAFETY: The value is not moved nor dropped after this read
		unsafe { ptr::copy_nonoverlapping(&raw const borrow[0], this_ptr, len); }
		DerefOwn::forget_contents(val);
		// SAFETY: `this` has been inhabited with a value
		unsafe { transmute(this) }
	}
}

#[cfg(feature = "alloc")]
impl<T: Sized, A: Allocator> TakeIn<[T], A> for Vec<T, A> {
	#[inline(always)]
	fn take_in(val: Own<[T]>, alloc: A) -> Self {
		let val = MaybeDangling::new(val);
		let borrow = &**val.as_ref();
		let len = borrow.len();
		let mut this: Vec<MaybeUninit<T>, A> = Box::new_uninit_slice_in(len, alloc).into_vec();
		let this_ptr = this[0].as_mut_ptr();
		// SAFETY: The value is not moved nor dropped after this read
		unsafe { ptr::copy_nonoverlapping(&raw const borrow[0], this_ptr, len); }
		DerefOwn::forget_contents(val);
		// SAFETY: `this` has been inhabited with a value
		unsafe { transmute(this) }
	}
}


#[cfg(feature = "alloc")]
impl Take<str> for String {
	#[inline(always)]
	fn take(val: Own<str>) -> Self {
		let val = MaybeDangling::new(val);
		let borrow = &**val.as_ref();
		let len = borrow.len();
		let mut this: Vec<MaybeUninit<u8>> = Box::new_uninit_slice(len).into_vec();
		let this_ptr = this[0].as_mut_ptr();
		// SAFETY: The value is not moved nor dropped after this read
		unsafe { ptr::copy_nonoverlapping(&raw const borrow.as_bytes()[0], this_ptr, len); }
		DerefOwn::forget_contents(val);
		// SAFETY: `this` has been inhabited with a value which is valid UTF-8
		unsafe { String::from_utf8_unchecked(transmute(this)) }
	}
}