java_spaghetti/refs/
arg.rs

1use std::marker::PhantomData;
2
3use jni_sys::*;
4
5use crate::{Env, Global, Local, Ref, ReferenceType};
6
7/// FFI: Use **Arg\<java::lang::Object\>** instead of jobject.  This represents a (null?) function argument.
8///
9/// Unlike most Java reference types from this library, this *can* be null.
10///
11/// FFI safe where a jobject is safe, assuming you match your types correctly.  Using the wrong type may result in
12/// soundness issues, but at least on Android mostly seems to just result in JNI aborting execution for the current
13/// process when calling methods on an instance of the wrong type.
14#[repr(transparent)]
15pub struct Arg<T: ReferenceType> {
16    object: jobject,
17    _class: PhantomData<T>,
18}
19
20impl<T: ReferenceType> Arg<T> {
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    pub fn as_raw(&self) -> jobject {
30        self.object
31    }
32
33    /// **unsafe**:  This assumes the argument belongs to the given Env/VM, which is technically unsound.  However, the
34    /// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
35    /// where Java directly invoked your function with an Env + arguments, is sound.
36    pub unsafe fn into_ref<'env>(self, env: Env<'env>) -> Option<Ref<'env, T>> {
37        if self.object.is_null() {
38            None
39        } else {
40            Some(Ref::from_raw(env, self.object))
41        }
42    }
43
44    /// **unsafe**:  This assumes the argument belongs to the given Env/VM, which is technically unsound.  However, the
45    /// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
46    /// where Java directly invoked your function with an Env + arguments, is sound.
47    pub unsafe fn into_local<'env>(self, env: Env<'env>) -> Option<Local<'env, T>> {
48        if self.object.is_null() {
49            None
50        } else {
51            Some(Local::from_raw(env, self.object))
52        }
53    }
54
55    /// **unsafe**:  This assumes the argument belongs to the given Env/VM, which is technically unsound.  However, the
56    /// intended use case of immediately converting any Arg s into ArgRef s at the start of a JNI callback,
57    /// where Java directly invoked your function with an Env + arguments, is sound.
58    pub unsafe fn into_global(self, env: Env) -> Option<Global<T>> {
59        if self.object.is_null() {
60            None
61        } else {
62            let jnienv = env.as_raw();
63            let object = ((**jnienv).v1_2.NewGlobalRef)(jnienv, self.object);
64            Some(Global::from_raw(env.vm(), object))
65        }
66    }
67}