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

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?")
}
}
}