#![feature(mem_copy_fn, box_into_inner)]
#![feature(const_trait_impl)]
#![feature(get_mut_unchecked)]
#![feature(new_uninit)]
#![feature(slice_ptr_len)]
#![feature(forget_unsized)]
use std::borrow::{BorrowMut, Cow};
use std::ffi::{CStr, CString, OsStr, OsString};
use std::marker::Destruct;
use std::mem::{ManuallyDrop, MaybeUninit, transmute};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::sync::Arc;
#[repr(transparent)]
struct AlwaysCopy<T: ?Sized>(T);
impl<T: ?Sized + Sized> Clone for AlwaysCopy<T> {
fn clone(&self) -> Self {
unsafe {
let mut ret = MaybeUninit::uninit().assume_init();
std::intrinsics::copy_nonoverlapping(self, &mut ret as _, 1);
ret
}
}
}
pub unsafe trait TryConsume<Target: ?Sized + ~const Destruct>: Sized {
fn try_consume_unsized<T>(self, f: impl FnOnce(*mut Target) -> T) -> Result<T, Self>;
fn try_consume(self) -> Result<Target, Self> where Target: Sized {
unsafe {
self.try_consume_unsized(|x| {
let mut ret = MaybeUninit::uninit().assume_init();
std::intrinsics::copy_nonoverlapping(x, &mut ret as _, 1);
ret
})
}
}
fn try_into_owned(self) -> Result<<Target as ToOwned>::Owned, Self>
where Target: ToOwned, <Target as ToOwned>::Owned: FromConsume<Target>
{
<Target as ToOwned>::Owned::try_from_consume(self)
}
}
pub unsafe trait Consume<Target: ?Sized + ~const Destruct>: TryConsume<Target> {
fn consume_unsized<T>(self, f: impl FnOnce(*mut Target) -> T) -> T;
fn consume(self) -> Target where Target: Sized {
unsafe {
self.consume_unsized(|x| {
let mut ret = MaybeUninit::uninit().assume_init();
std::intrinsics::copy_nonoverlapping(x, &mut ret as _, 1);
ret
})
}
}
fn into_owned(self) -> <Target as ToOwned>::Owned
where Target: ToOwned, <Target as ToOwned>::Owned: FromConsume<Target>
{
<Target as ToOwned>::Owned::from_consume(self)
}
}
unsafe impl<T> TryConsume<T> for T {
fn try_consume_unsized<U>(self, f: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
Ok(self.consume_unsized(f))
}
}
unsafe impl<T> Consume<T> for T {
fn consume_unsized<U>(mut self, f: impl FnOnce(*mut T) -> U) -> U {
let ret = f(&mut self as _);
std::mem::forget_unsized(self);
ret
}
}
pub trait FromConsume<From: ?Sized>: Sized {
unsafe fn from_consume_raw(p: *mut From) -> Self;
fn try_from_consume<T: TryConsume<From>>(consume: T) -> Result<Self, T> {
unsafe {
consume.try_consume_unsized(|x| Self::from_consume_raw(x))
}
}
fn from_consume<T: Consume<From> + TryConsume<From>>(consume: T) -> Self {
unsafe {
consume.consume_unsized(|x| Self::from_consume_raw(x))
}
}
}
macro_rules! unsized_copy {
($callback_macro:ident) => {
$callback_macro!(str);
$callback_macro!(CStr);
$callback_macro!(OsStr);
$callback_macro!(Path);
};
}
impl<T> FromConsume<[T]> for Vec<T> {
unsafe fn from_consume_raw(p: *mut [T]) -> Self {
let ret = (p as *mut [AlwaysCopy<T>]).as_ref().unwrap_unchecked().to_vec();
transmute(ret)
}
}
unsafe impl<T> TryConsume<[T]> for Vec<T> where [T]: ToOwned<Owned=Vec<T>> {
fn try_consume_unsized<U>(self, f: impl FnOnce(*mut [T]) -> U) -> Result<U, Self> {
Ok(self.consume_unsized(f))
}
fn try_into_owned(self) -> Result<<[T] as ToOwned>::Owned, Self> {
Ok(self)
}
}
unsafe impl<T> Consume<[T]> for Vec<T> where [T]: ToOwned<Owned=Vec<T>> {
fn consume_unsized<U>(mut self, f: impl FnOnce(*mut [T]) -> U) -> U {
let ret = f(self.as_mut_slice() as _);
unsafe { transmute::<_, Vec<ManuallyDrop<T>>>(self); }
ret
}
fn into_owned(self) -> <[T] as ToOwned>::Owned {
self
}
}
impl FromConsume<str> for String {
unsafe fn from_consume_raw(p: *mut str) -> Self {
p.as_ref().unwrap_unchecked().to_string()
}
}
unsafe impl TryConsume<str> for String {
fn try_consume_unsized<T>(self, f: impl FnOnce(*mut str) -> T) -> Result<T, Self> {
Ok(self.consume_unsized(f))
}
fn try_into_owned(self) -> Result<String, Self> {
Ok(self)
}
}
unsafe impl Consume<str> for String {
fn consume_unsized<T>(mut self, f: impl FnOnce(*mut str) -> T) -> T {
f(self.as_mut_str() as _)
}
fn into_owned(self) -> String {
self
}
}
impl FromConsume<CStr> for CString {
unsafe fn from_consume_raw(p: *mut CStr) -> Self {
p.as_ref().unwrap_unchecked().to_owned()
}
}
unsafe impl TryConsume<CStr> for CString {
fn try_consume_unsized<T>(self, f: impl FnOnce(*mut CStr) -> T) -> Result<T, Self> {
Ok(self.consume_unsized(f))
}
fn try_into_owned(self) -> Result<CString, Self> {
Ok(self)
}
}
unsafe impl Consume<CStr> for CString {
fn consume_unsized<T>(self, f: impl FnOnce(*mut CStr) -> T) -> T {
f(self.as_c_str() as *const _ as *mut _)
}
fn into_owned(self) -> CString {
self
}
}
impl FromConsume<OsStr> for OsString {
unsafe fn from_consume_raw(p: *mut OsStr) -> Self {
p.as_ref().unwrap_unchecked().to_owned()
}
}
unsafe impl TryConsume<OsStr> for OsString {
fn try_consume_unsized<T>(self, f: impl FnOnce(*mut OsStr) -> T) -> Result<T, Self> {
Ok(self.consume_unsized(f))
}
fn try_into_owned(self) -> Result<OsString, Self> {
Ok(self)
}
}
unsafe impl Consume<OsStr> for OsString {
fn consume_unsized<T>(self, f: impl FnOnce(*mut OsStr) -> T) -> T {
f(self.as_os_str() as *const _ as *mut _)
}
fn into_owned(self) -> OsString {
self
}
}
impl FromConsume<Path> for PathBuf {
unsafe fn from_consume_raw(p: *mut Path) -> Self {
p.as_ref().unwrap_unchecked().to_owned()
}
}
unsafe impl TryConsume<Path> for PathBuf {
fn try_consume_unsized<T>(self, f: impl FnOnce(*mut Path) -> T) -> Result<T, Self> {
Ok(self.consume_unsized(f))
}
fn try_into_owned(self) -> Result<Self, Self> {
Ok(self)
}
}
unsafe impl Consume<Path> for PathBuf {
fn consume_unsized<T>(self, f: impl FnOnce(*mut Path) -> T) -> T {
f(self.as_path() as *const _ as *mut _)
}
fn into_owned(self) -> Self {
self
}
}
unsafe impl<T: ?Sized> TryConsume<T> for Box<T> {
fn try_consume_unsized<U>(self, f: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
Ok(self.consume_unsized(f))
}
fn try_consume(self) -> Result<T, Self> where T: Sized {
Ok(self.consume())
}
}
unsafe impl<T: ?Sized> Consume<T> for Box<T> {
fn consume_unsized<U>(mut self, f: impl FnOnce(*mut T) -> U) -> U {
let ret = f(self.borrow_mut() as *mut T);
unsafe { transmute::<_, Box<ManuallyDrop<T>>>(self); }
ret
}
fn consume(self) -> T where T: Sized {
Box::into_inner(self)
}
}
impl<T> FromConsume<T> for Box<T> {
unsafe fn from_consume_raw(p: *mut T) -> Self {
let x = Box::from_raw(p as *mut AlwaysCopy<T>);
let ret = x.clone();
Box::leak(x);
transmute(ret)
}
}
impl<T> FromConsume<[T]> for Box<[T]> {
unsafe fn from_consume_raw(p: *mut [T]) -> Self {
let x = Box::from_raw(p as *mut [AlwaysCopy<T>]);
let ret = x.clone();
Box::leak(x);
transmute(ret)
}
}
macro_rules! box_unsized {
($t:ty) => {
impl FromConsume<$t> for Box<$t> {
unsafe fn from_consume_raw(p: *mut $t) -> Self {
let x = Box::from_raw(p);
let ret = x.clone();
Box::leak(x);
transmute(ret)
}
}
};
}
unsized_copy!(box_unsized);
unsafe impl<T: ?Sized> TryConsume<T> for Arc<T> {
fn try_consume_unsized<U>(mut self, f: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
if let Some(x) = Arc::get_mut(&mut self) {
let ret = f(x as _);
unsafe { transmute::<_, Arc<ManuallyDrop<T>>>(self); }
Ok(ret)
} else {
Err(self)
}
}
}
impl<T> FromConsume<T> for Arc<T> {
unsafe fn from_consume_raw(p: *mut T) -> Self {
let x = Box::from_raw(p as *mut AlwaysCopy<T>);
let mut ret: Arc<MaybeUninit<AlwaysCopy<T>>> = Arc::new_uninit();
std::intrinsics::copy_nonoverlapping(p as *const AlwaysCopy<T>, Arc::get_mut_unchecked(&mut ret).assume_init_mut() as *mut AlwaysCopy<T>, 1);
Box::leak(x);
transmute(ret.assume_init())
}
}
impl<T> FromConsume<[T]> for Arc<[T]> {
unsafe fn from_consume_raw(p: *mut [T]) -> Self {
let x = Box::from_raw(p as *mut [AlwaysCopy<T>]);
let mut ret: Arc<[MaybeUninit<AlwaysCopy<T>>]> = Arc::new_uninit_slice(p.len());
std::intrinsics::copy_nonoverlapping(p as *const AlwaysCopy<T>, Arc::get_mut_unchecked(&mut ret).as_mut_ptr() as *mut AlwaysCopy<T>, p.len());
Box::leak(x);
transmute(ret.assume_init())
}
}
macro_rules! arc_unsized {
($t:ty) => {
impl FromConsume<$t> for Arc<$t> {
unsafe fn from_consume_raw(p: *mut $t) -> Self {
let x = Box::from_raw(p);
let ret = (&*x).into();
Box::leak(x);
ret
}
}
};
}
unsized_copy!(arc_unsized);
unsafe impl<T: ?Sized> TryConsume<T> for Rc<T> {
fn try_consume_unsized<U>(mut self, f: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
if let Some(x) = Rc::get_mut(&mut self) {
let ret = f(x as _);
unsafe { transmute::<_, Rc<ManuallyDrop<T>>>(self); }
Ok(ret)
} else {
Err(self)
}
}
}
impl<T> FromConsume<T> for Rc<T> {
unsafe fn from_consume_raw(p: *mut T) -> Self {
let x = Box::from_raw(p as *mut AlwaysCopy<T>);
let mut ret: Rc<MaybeUninit<AlwaysCopy<T>>> = Rc::new_uninit();
std::intrinsics::copy_nonoverlapping(p as *const AlwaysCopy<T>, Rc::get_mut_unchecked(&mut ret).assume_init_mut() as *mut AlwaysCopy<T>, 1);
Box::leak(x);
transmute(ret.assume_init())
}
}
impl<T> FromConsume<[T]> for Rc<[T]> {
unsafe fn from_consume_raw(p: *mut [T]) -> Self {
let x = Box::from_raw(p as *mut [AlwaysCopy<T>]);
let mut ret: Rc<[MaybeUninit<AlwaysCopy<T>>]> = Rc::new_uninit_slice(p.len());
std::intrinsics::copy_nonoverlapping(p as *const AlwaysCopy<T>, Rc::get_mut_unchecked(&mut ret).as_mut_ptr() as *mut AlwaysCopy<T>, p.len());
Box::leak(x);
transmute(ret.assume_init())
}
}
macro_rules! rc_unsized {
($t:ty) => {
impl FromConsume<$t> for Rc<$t> {
unsafe fn from_consume_raw(p: *mut $t) -> Self {
let x = Box::from_raw(p);
let ret = (&*x).into();
Box::leak(x);
ret
}
}
};
}
unsized_copy!(rc_unsized);
unsafe impl<T: ToOwned + ?Sized> TryConsume<T> for Cow<'_, T> where T::Owned: TryConsume<T> {
fn try_consume_unsized<U>(self, f: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
if let Cow::Owned(owned) = self {
owned.try_consume_unsized(f).map_err(|x| Cow::Owned(x))
} else {
Err(self)
}
}
fn try_into_owned(self) -> Result<T::Owned, Self> {
if let Cow::Owned(owned) = self {
Ok(owned)
} else {
Err(self)
}
}
}
impl<T: ToOwned + ?Sized, U> FromConsume<U> for Cow<'_, T> where T::Owned: FromConsume<U> {
unsafe fn from_consume_raw(p: *mut U) -> Self {
Cow::Owned(<T::Owned as FromConsume<U>>::from_consume_raw(p))
}
}
unsafe impl<T> TryConsume<T> for &T {
fn try_consume_unsized<U>(self, _: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
Err(self)
}
}
unsafe impl<T> TryConsume<T> for &mut T {
fn try_consume_unsized<U>(self, _: impl FnOnce(*mut T) -> U) -> Result<U, Self> {
Err(self)
}
}