|
|
|
@ -1,15 +1,29 @@
|
|
|
|
|
#[allow(unused_imports)]
|
|
|
|
|
use std::{
|
|
|
|
|
ops::{
|
|
|
|
|
Drop,
|
|
|
|
|
Deref,
|
|
|
|
|
DerefMut,
|
|
|
|
|
},
|
|
|
|
|
mem::replace,
|
|
|
|
|
mem::{
|
|
|
|
|
replace,
|
|
|
|
|
MaybeUninit,
|
|
|
|
|
},
|
|
|
|
|
fmt,
|
|
|
|
|
};
|
|
|
|
|
use cfg_if::cfg_if;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
|
|
|
type OptFn<T,F> = MaybeUninit<(T,F)>;
|
|
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
|
type OptFn<T,F> = Option<(T,F)>;
|
|
|
|
|
|
|
|
|
|
/// Allow for running function on drop, to support moving out of a larger structure.
|
|
|
|
|
pub struct PhantomDrop<T,F>(Option<(T,F)>)
|
|
|
|
|
///
|
|
|
|
|
/// # Notes
|
|
|
|
|
/// This type has a safe ABI with runtime checks when compiled with `debug_assertions`, without them an unsafe but lower cost ABI is preferred.
|
|
|
|
|
pub struct PhantomDrop<T,F>(OptFn<T,F>)
|
|
|
|
|
where F: FnOnce(T);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -27,9 +41,20 @@ impl<T,F> Drop for PhantomDrop<T,F>
|
|
|
|
|
where F:FnOnce(T)
|
|
|
|
|
{
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
if let Some((value, func)) = replace(&mut self.0, None)
|
|
|
|
|
{
|
|
|
|
|
func(value);
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
if let Some((value, func)) = replace(&mut self.0, None)
|
|
|
|
|
{
|
|
|
|
|
func(value);
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Double drop?")
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
let (value, func) = unsafe {
|
|
|
|
|
(&mut self.0 as *mut OptFn<T,F>).read().assume_init()
|
|
|
|
|
};
|
|
|
|
|
func(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -42,14 +67,56 @@ where F:FnOnce(T)
|
|
|
|
|
#[cfg(nightly)]
|
|
|
|
|
pub const fn new(value: T, func: F) -> Self
|
|
|
|
|
{
|
|
|
|
|
Self(Some((value,func)))
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
Self(Some((value,func)))
|
|
|
|
|
} else {
|
|
|
|
|
Self(MaybeUninit::new((value,func)))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Create a new `PhantomDrop` with a drop closure and a value.
|
|
|
|
|
#[cfg(not(nightly))]
|
|
|
|
|
pub fn new(value: T, func: F) -> Self
|
|
|
|
|
{
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
Self(Some((value,func)))
|
|
|
|
|
} else {
|
|
|
|
|
Self(MaybeUninit::new((value,func)))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
|
|
|
#[inline]
|
|
|
|
|
fn get_ref<'a>(&'a self) -> &'a (T, F)
|
|
|
|
|
{
|
|
|
|
|
Self(Some((value,func)))
|
|
|
|
|
unsafe {
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(nightly)] {
|
|
|
|
|
self.0.get_ref()
|
|
|
|
|
} else {
|
|
|
|
|
std::mem::transmute::<_,&'a T>(self.0.as_ptr())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
|
|
|
#[inline]
|
|
|
|
|
fn get_mut<'a>(&'a mut self) -> &'a mut (T, F)
|
|
|
|
|
{
|
|
|
|
|
unsafe {
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(nightly)] {
|
|
|
|
|
self.0.get_mut()
|
|
|
|
|
} else {
|
|
|
|
|
std::mem::transmute::<_,&'a T>(self.0.as_mut_ptr())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -60,11 +127,18 @@ where F:FnOnce(T)
|
|
|
|
|
type Target = T;
|
|
|
|
|
fn deref(&self) -> &Self::Target
|
|
|
|
|
{
|
|
|
|
|
if let Some((t, _)) = &self.0
|
|
|
|
|
{
|
|
|
|
|
t
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Double drop?")
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
if let Some((t, _)) = &self.0
|
|
|
|
|
{
|
|
|
|
|
t
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Double drop?")
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
let (t, _) = self.get_ref();
|
|
|
|
|
t
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -75,11 +149,19 @@ where F:FnOnce(T)
|
|
|
|
|
{
|
|
|
|
|
fn deref_mut(&mut self) -> &mut <Self as Deref>::Target
|
|
|
|
|
{
|
|
|
|
|
if let Some((t, _)) = &mut self.0
|
|
|
|
|
{
|
|
|
|
|
t
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Double drop?")
|
|
|
|
|
cfg_if! {
|
|
|
|
|
if #[cfg(debug_assertions)] {
|
|
|
|
|
if let Some((t, _)) = &mut self.0
|
|
|
|
|
{
|
|
|
|
|
t
|
|
|
|
|
} else {
|
|
|
|
|
panic!("Double drop?")
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
let (t, _) = self.get_mut();
|
|
|
|
|
t
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|