1 use std::marker::PhantomData;
2 
3 use crate::sys::jobject;
4 
5 #[cfg(doc)]
6 use crate::{objects::GlobalRef, JNIEnv};
7 
8 /// Wrapper around [`sys::jobject`] that adds a lifetime to ensure that
9 /// the underlying JNI pointer won't be accessible to safe Rust code if the
10 /// object reference is released.
11 ///
12 /// It matches C's representation of the raw pointer, so it can be used in any
13 /// of the extern function argument positions that would take a `jobject`.
14 ///
15 /// Most other types in the `objects` module deref to this, as they do in the C
16 /// representation.
17 ///
18 /// The lifetime `'local` represents the local reference frame that this
19 /// reference belongs to. See the [`JNIEnv`] documentation for more information
20 /// about local reference frames. If `'local` is `'static`, then this reference
21 /// does not belong to a local reference frame, that is, it is either null or a
22 /// [global reference][GlobalRef].
23 ///
24 /// Note that an *owned* `JObject` is always a local reference and will never
25 /// have the `'static` lifetime. [`GlobalRef`] does implement
26 /// <code>[AsRef]&lt;JObject&lt;'static>></code>, but this only yields a
27 /// *borrowed* `&JObject<'static>`, never an owned `JObject<'static>`.
28 ///
29 /// Local references belong to a single thread and are not safe to share across
30 /// threads. This type implements [`Send`] and [`Sync`] if and only if the
31 /// lifetime `'local` is `'static`.
32 #[repr(transparent)]
33 #[derive(Debug)]
34 pub struct JObject<'local> {
35     internal: jobject,
36     lifetime: PhantomData<&'local ()>,
37 }
38 
39 unsafe impl Send for JObject<'static> {}
40 unsafe impl Sync for JObject<'static> {}
41 
42 impl<'local> AsRef<JObject<'local>> for JObject<'local> {
as_ref(&self) -> &JObject<'local>43     fn as_ref(&self) -> &JObject<'local> {
44         self
45     }
46 }
47 
48 impl<'local> AsMut<JObject<'local>> for JObject<'local> {
as_mut(&mut self) -> &mut JObject<'local>49     fn as_mut(&mut self) -> &mut JObject<'local> {
50         self
51     }
52 }
53 
54 impl<'local> ::std::ops::Deref for JObject<'local> {
55     type Target = jobject;
56 
deref(&self) -> &Self::Target57     fn deref(&self) -> &Self::Target {
58         &self.internal
59     }
60 }
61 
62 impl<'local> JObject<'local> {
63     /// Creates a [`JObject`] that wraps the given `raw` [`jobject`]
64     ///
65     /// # Safety
66     ///
67     /// `raw` may be a null pointer. If `raw` is not a null pointer, then:
68     ///
69     /// * `raw` must be a valid raw JNI local reference.
70     /// * There must not be any other `JObject` representing the same local reference.
71     /// * The lifetime `'local` must not outlive the local reference frame that the local reference
72     ///   was created in.
from_raw(raw: jobject) -> Self73     pub unsafe fn from_raw(raw: jobject) -> Self {
74         Self {
75             internal: raw,
76             lifetime: PhantomData,
77         }
78     }
79 
80     /// Returns the raw JNI pointer.
as_raw(&self) -> jobject81     pub fn as_raw(&self) -> jobject {
82         self.internal
83     }
84 
85     /// Unwrap to the internal jni type.
into_raw(self) -> jobject86     pub fn into_raw(self) -> jobject {
87         self.internal
88     }
89 
90     /// Creates a new null reference.
91     ///
92     /// Null references are always valid and do not belong to a local reference frame. Therefore,
93     /// the returned `JObject` always has the `'static` lifetime.
null() -> JObject<'static>94     pub fn null() -> JObject<'static> {
95         unsafe { JObject::from_raw(std::ptr::null_mut() as jobject) }
96     }
97 }
98 
99 impl<'local> std::default::Default for JObject<'local> {
default() -> Self100     fn default() -> Self {
101         Self::null()
102     }
103 }
104