use std::{borrow::Cow, marker::PhantomData, ops::Deref};
use crate::{
Env,
errors::Result,
jni_str,
objects::{Global, JClass, LoaderContext},
strings::JNIStr,
sys::jobject,
};
use super::Reference;
#[cfg(doc)]
use crate::{objects::JString, refs::Weak};
#[repr(transparent)]
#[derive(Debug)]
pub struct JObject<'local> {
internal: jobject,
lifetime: PhantomData<&'local ()>,
}
unsafe impl Send for JObject<'static> {}
unsafe impl Sync for JObject<'static> {}
impl<'local> AsRef<JObject<'local>> for JObject<'local> {
fn as_ref(&self) -> &JObject<'local> {
self
}
}
impl<'local> AsMut<JObject<'local>> for JObject<'local> {
fn as_mut(&mut self) -> &mut JObject<'local> {
self
}
}
impl ::std::ops::Deref for JObject<'_> {
type Target = jobject;
fn deref(&self) -> &Self::Target {
&self.internal
}
}
pub(crate) struct JObjectAPI {
class: Global<JClass<'static>>,
}
impl JObjectAPI {
pub(crate) fn get(env: &Env<'_>) -> Result<&'static Self> {
static API: std::sync::OnceLock<JObjectAPI> = std::sync::OnceLock::new();
if let Some(api) = API.get() {
return Ok(api);
}
let api = env.with_local_frame(8, |env| -> crate::errors::Result<_> {
let class = env.find_class(jni_str!("java/lang/Object"))?;
let class = env.new_global_ref(class)?;
Ok(JObjectAPI { class })
})?;
let _ = API.set(api);
Ok(API.get().unwrap())
}
}
impl JObject<'_> {
pub unsafe fn from_raw<'local>(_env: &Env<'local>, raw: jobject) -> JObject<'local> {
unsafe { JObject::kind_from_raw(raw) }
}
pub const fn null() -> JObject<'static> {
JObject {
internal: std::ptr::null_mut(),
lifetime: PhantomData,
}
}
pub const fn as_raw(&self) -> jobject {
self.internal
}
pub const fn into_raw(self) -> jobject {
self.internal
}
}
impl std::default::Default for JObject<'_> {
fn default() -> Self {
Self::null()
}
}
unsafe impl Reference for JObject<'_> {
type Kind<'env> = JObject<'env>;
type GlobalKind = JObject<'static>;
fn as_raw(&self) -> jobject {
self.as_raw()
}
fn class_name() -> Cow<'static, JNIStr> {
Cow::Borrowed(jni_str!("java.lang.Object"))
}
fn lookup_class<'caller>(
env: &Env<'_>,
_loader_context: &LoaderContext,
) -> crate::errors::Result<impl Deref<Target = Global<JClass<'static>>> + 'caller> {
let api = JObjectAPI::get(env)?;
Ok(&api.class)
}
unsafe fn kind_from_raw<'env>(local_ref: jobject) -> Self::Kind<'env> {
JObject {
internal: local_ref,
lifetime: PhantomData,
}
}
unsafe fn global_kind_from_raw(global_ref: jobject) -> Self::GlobalKind {
JObject {
internal: global_ref,
lifetime: PhantomData,
}
}
}