use crate::{AssignableTo, Env, Global, JavaDebug, JavaDisplay, Ref, ReferenceType, Return};
use jni_sys::*;
use std::{
fmt::{self, Debug, Display, Formatter},
mem::transmute,
ops::Deref,
};
#[repr(C)] pub struct Local<'env, T: ReferenceType> {
ref_: Ref<'env, T>,
}
impl<'env, T: ReferenceType> Local<'env, T> {
pub unsafe fn from_raw(env: Env<'env>, object: jobject) -> Self {
Self {
ref_: unsafe { Ref::from_raw(env, object) },
}
}
pub fn env(&self) -> Env<'env> {
self.ref_.env()
}
pub fn as_raw(&self) -> jobject {
self.ref_.as_raw()
}
pub fn into_raw(self) -> jobject {
let object = self.ref_.as_raw();
std::mem::forget(self); object
}
pub fn leak(self) -> Ref<'env, T> {
unsafe { Ref::from_raw(self.env(), self.into_raw()) }
}
pub fn as_global(&self) -> Global<T> {
self.as_ref().as_global()
}
pub fn as_return(&self) -> Return<'env, T> {
self.clone().into_return()
}
pub fn into_return(self) -> Return<'env, T> {
unsafe { Return::from_raw(self.into_raw()) }
}
pub fn cast<U: ReferenceType>(self) -> Result<Local<'env, U>, crate::CastError> {
self.as_ref().check_assignable::<U>()?;
Ok(unsafe { transmute::<Local<'_, T>, Local<'_, U>>(self) })
}
pub fn upcast<U: ReferenceType>(self) -> Local<'env, U>
where
T: AssignableTo<U>,
{
unsafe { transmute(self) }
}
}
impl<'env, T: ReferenceType> From<Ref<'env, T>> for Local<'env, T> {
fn from(x: Ref<'env, T>) -> Self {
x.as_local()
}
}
impl<'env, T: ReferenceType> From<&Local<'env, T>> for Local<'env, T> {
fn from(x: &Local<'env, T>) -> Self {
x.clone()
}
}
impl<'env, T: ReferenceType> From<&Ref<'env, T>> for Local<'env, T> {
fn from(x: &Ref<'env, T>) -> Self {
x.as_local()
}
}
impl<'env, T: ReferenceType> AsRef<Ref<'env, T>> for Local<'env, T> {
fn as_ref(&self) -> &Ref<'env, T> {
&self.ref_
}
}
impl<'env, T: ReferenceType> Deref for Local<'env, T> {
type Target = Ref<'env, T>;
fn deref(&self) -> &Self::Target {
&self.ref_
}
}
impl<'env, T: ReferenceType> Clone for Local<'env, T> {
fn clone(&self) -> Self {
let env = self.env().as_raw();
let object = unsafe { ((**env).v1_2.NewLocalRef)(env, self.as_raw()) };
assert!(!object.is_null());
unsafe { Self::from_raw(self.env(), object) }
}
}
impl<'env, T: ReferenceType> Drop for Local<'env, T> {
fn drop(&mut self) {
let env = self.env().as_raw();
unsafe { ((**env).v1_2.DeleteLocalRef)(env, self.as_raw()) }
}
}
impl<'env, T: JavaDebug> Debug for Local<'env, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
T::fmt(self, f)
}
}
impl<'env, T: JavaDisplay> Display for Local<'env, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
T::fmt(self, f)
}
}