use std::{fmt::Debug, rc::Rc};
struct HandleWrapper<T> {
handle: *mut T,
cleanup_fn: Option<fn(*mut T)>,
}
impl<T> Drop for HandleWrapper<T> {
fn drop(&mut self) {
if let Some(cleanup_fn) = self.cleanup_fn {
(cleanup_fn)(self.handle);
#[cfg(feature = "debug_print")]
println!(" close Handle<{}>({:p})", name::<T>(), self.handle);
} else {
#[cfg(feature = "debug_print")]
println!(" drop Handle<{}>({:p})", name::<T>(), self.handle);
}
}
}
#[derive(Clone)]
pub struct Handle<T> {
inner: Rc<HandleWrapper<T>>,
}
impl<T> Handle<T> {
pub fn new(handle: *mut T, cleanup_fn: Option<fn(*mut T)>) -> Self {
#[cfg(feature = "debug_print")]
println!(" new Handle<{}>({:p})", name::<T>(), handle);
Handle {
inner: Rc::new(HandleWrapper { handle, cleanup_fn }),
}
}
pub fn new_const(handle: *const T) -> Self {
#[cfg(feature = "debug_print")]
println!(" const Handle<{}>({:p})", name::<T>(), handle);
Handle {
inner: Rc::new(HandleWrapper {
handle: handle as *mut T,
cleanup_fn: None, }),
}
}
pub fn handle(&self) -> *mut T {
self.inner.handle
}
}
impl<T> Debug for Handle<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Handle<{}>({:p})", name::<T>(), self.inner.handle)
}
}
fn name<T>() -> String {
std::any::type_name::<T>()
.replace("pdfium::c_api::pdfium_types::fpdf_", "") .replace("_t__", "") }