use std::{
mem::ManuallyDrop,
ops::{Deref, DerefMut},
ptr,
};
use log::debug;
use crate::{objects::JObject, JNIEnv};
#[derive(Debug)]
pub struct AutoLocal<'local, T>
where
T: Into<JObject<'local>>,
{
obj: ManuallyDrop<T>,
env: JNIEnv<'local>,
}
impl<'local, T> AutoLocal<'local, T>
where
T: Into<JObject<'local>>,
{
pub fn new(obj: T, env: &JNIEnv<'local>) -> Self {
let env = unsafe { env.unsafe_clone() };
AutoLocal {
obj: ManuallyDrop::new(obj),
env,
}
}
pub fn forget(self) -> T {
let mut self_md = ManuallyDrop::new(self);
unsafe {
ptr::drop_in_place(&mut self_md.env);
ptr::read(&*self_md.obj)
}
}
}
impl<'local, T> Drop for AutoLocal<'local, T>
where
T: Into<JObject<'local>>,
{
fn drop(&mut self) {
let obj = unsafe { ManuallyDrop::take(&mut self.obj) };
let res = self.env.delete_local_ref(obj);
match res {
Ok(()) => {}
Err(e) => debug!("error dropping global ref: {:#?}", e),
}
}
}
impl<'local, T, U> AsRef<U> for AutoLocal<'local, T>
where
T: AsRef<U> + Into<JObject<'local>>,
{
fn as_ref(&self) -> &U {
self.obj.as_ref()
}
}
impl<'local, T, U> AsMut<U> for AutoLocal<'local, T>
where
T: AsMut<U> + Into<JObject<'local>>,
{
fn as_mut(&mut self) -> &mut U {
self.obj.as_mut()
}
}
impl<'local, T> Deref for AutoLocal<'local, T>
where
T: Into<JObject<'local>>,
{
type Target = T;
fn deref(&self) -> &Self::Target {
&self.obj
}
}
impl<'local, T> DerefMut for AutoLocal<'local, T>
where
T: Into<JObject<'local>>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.obj
}
}