You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
86 lines
1.4 KiB
86 lines
1.4 KiB
use std::{
|
|
ops::{
|
|
Drop,
|
|
Deref,
|
|
DerefMut,
|
|
},
|
|
mem::replace,
|
|
fmt,
|
|
};
|
|
|
|
/// Allow for running function on drop, to support moving out of a larger structure.
|
|
pub struct PhantomDrop<T,F>(Option<(T,F)>)
|
|
where F: FnOnce(T);
|
|
|
|
|
|
impl<T,F> fmt::Debug for PhantomDrop<T,F>
|
|
where F:FnOnce(T),
|
|
T: fmt::Debug,
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
{
|
|
self.deref().fmt(f)
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl<T,F> PhantomDrop<T,F>
|
|
where F:FnOnce(T)
|
|
{
|
|
/// Create a new `PhantomDrop` with a drop closure and a value.
|
|
#[cfg(nightly)]
|
|
pub const fn new(value: T, func: F) -> Self
|
|
{
|
|
Self(Some((value,func)))
|
|
}
|
|
|
|
/// Create a new `PhantomDrop` with a drop closure and a value.
|
|
#[cfg(not(nightly))]
|
|
pub fn new(value: T, func: F) -> Self
|
|
{
|
|
Self(Some((value,func)))
|
|
}
|
|
}
|
|
|
|
|
|
impl<T,F> Deref for PhantomDrop<T,F>
|
|
where F:FnOnce(T)
|
|
{
|
|
type Target = T;
|
|
fn deref(&self) -> &Self::Target
|
|
{
|
|
if let Some((t, _)) = &self.0
|
|
{
|
|
t
|
|
} else {
|
|
panic!("Double drop?")
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl<T,F> DerefMut for PhantomDrop<T,F>
|
|
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?")
|
|
}
|
|
}
|
|
}
|