java_oxide/refs/
arg.rs

1use crate::{Env, Global, Local, Ref, ReferenceType};
2use jni_sys::*;
3use std::marker::PhantomData;
4
5/// FFI: Use **Arg\<java::lang::Object\>** instead of `jobject`.  This represents a (null?) function argument.
6///
7/// Unlike most Java reference types from this library, this *can* be null.
8///
9/// FFI safe where a `jobject` is safe, assuming you match your types correctly.  Using the wrong type may result in
10/// soundness issues, but at least on Android mostly seems to just result in JNI aborting execution for the current
11/// process when calling methods on an instance of the wrong type.
12#[repr(transparent)]
13pub struct Arg<T: ReferenceType> {
14    object: jobject,
15    _class: PhantomData<T>,
16}
17
18impl<T: ReferenceType> Arg<T> {
19    /// # Safety
20    ///
21    /// **unsafe**:  There's no guarantee the `jobject` being passed is valid or null, nor any means of checking it.
22    pub unsafe fn from_raw(object: jobject) -> Self {
23        Self {
24            object,
25            _class: PhantomData,
26        }
27    }
28
29    /// Returns the raw JNI reference pointer.
30    pub fn as_raw(&self) -> jobject {
31        self.object
32    }
33
34    /// # Safety
35    ///
36    /// **unsafe**:  This assumes the argument belongs to the given [Env], which is technically unsound.  However,
37    /// the intended use case of immediately converting any [Arg] into [Ref] at the start of a JNI callback,
38    /// where Java directly invoked your function with an [Env] + arguments, is sound.
39    pub unsafe fn into_ref<'env>(self, env: Env<'env>) -> Option<Ref<'env, T>> {
40        if self.object.is_null() {
41            None
42        } else {
43            Some(unsafe { Ref::from_raw(env, self.object) })
44        }
45    }
46
47    /// # Safety
48    ///
49    /// **unsafe**:  This assumes the argument belongs to the given [Env], which is technically unsound.  However,
50    /// the intended use case of immediately converting any [Arg] into [Local] at the start of a JNI callback,
51    /// where Java directly invoked your function with an [Env] + arguments, is sound.
52    pub unsafe fn into_local<'env>(self, env: Env<'env>) -> Option<Local<'env, T>> {
53        unsafe { self.into_ref(env) }.map(|r| r.as_local())
54    }
55
56    /// This equals [Arg::into_ref] + [Ref::as_global].
57    ///
58    /// # Safety
59    ///
60    /// **unsafe**:  The same as [Arg::into_ref].
61    pub unsafe fn into_global(self, env: Env) -> Option<Global<T>> {
62        unsafe { self.into_ref(env) }.as_ref().map(Ref::as_global)
63    }
64}