use std::mem::forget;
use std::ops::{Deref, DerefMut, Drop};
pub trait Destroy<Args> {
fn destroy(self, args: Args);
}
pub struct MustDestroy<T> {
wrapped: T
}
impl<T> MustDestroy<T> {
pub fn new(item: T) -> Self {
MustDestroy {
wrapped: item,
}
}
pub fn into_inner(mut self) -> T {
let wrapped = std::mem::replace(&mut self.wrapped, unsafe { std::mem::zeroed() });
forget(self);
wrapped
}
}
impl<Args, T: Destroy<Args>> Destroy<Args> for MustDestroy<T> {
fn destroy(self, args: Args) {
self.into_inner().destroy(args);
}
}
impl<T: Destroy<()>> MustDestroy<T> {
pub fn destroy(self) {
Destroy::destroy(self, ())
}
}
impl<T> Drop for MustDestroy<T> {
fn drop(&mut self) {
panic!("Can not drop, must call destroy.");
}
}
impl<T> Deref for MustDestroy<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.wrapped
}
}
impl<T> DerefMut for MustDestroy<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.wrapped
}
}
#[cfg(test)]
mod tests {
use crate::{Destroy, MustDestroy};
#[test]
fn test_readme() {
struct MyDestroyableItem;
impl Destroy<(&'_ str, i32)> for MyDestroyableItem {
fn destroy(self, args: (&str, i32)) {
assert_eq!("Test String", args.0);
assert_eq!(12, args.1);
}
}
let destroy_me = MustDestroy::new(MyDestroyableItem);
destroy_me.destroy(("Test String", 12));
}
}