1 use std::marker::PhantomData;
2 
3 use crate::{
4     objects::JObject,
5     sys::{jarray, jobject},
6 };
7 
8 use super::TypeArray;
9 
10 #[cfg(doc)]
11 use crate::JNIEnv;
12 
13 /// Lifetime'd representation of a [`jarray`] which wraps a [`JObject`] reference
14 ///
15 /// This is a wrapper type for a [`JObject`] local reference that's used to
16 /// differentiate JVM array types.
17 #[repr(transparent)]
18 #[derive(Debug)]
19 pub struct JPrimitiveArray<'local, T: TypeArray> {
20     obj: JObject<'local>,
21     lifetime: PhantomData<&'local T>,
22 }
23 
24 impl<'local, T: TypeArray> AsRef<JPrimitiveArray<'local, T>> for JPrimitiveArray<'local, T> {
as_ref(&self) -> &JPrimitiveArray<'local, T>25     fn as_ref(&self) -> &JPrimitiveArray<'local, T> {
26         self
27     }
28 }
29 
30 impl<'local, T: TypeArray> AsMut<JPrimitiveArray<'local, T>> for JPrimitiveArray<'local, T> {
as_mut(&mut self) -> &mut JPrimitiveArray<'local, T>31     fn as_mut(&mut self) -> &mut JPrimitiveArray<'local, T> {
32         self
33     }
34 }
35 
36 impl<'local, T: TypeArray> AsRef<JObject<'local>> for JPrimitiveArray<'local, T> {
as_ref(&self) -> &JObject<'local>37     fn as_ref(&self) -> &JObject<'local> {
38         &self.obj
39     }
40 }
41 
42 impl<'local, T: TypeArray> ::std::ops::Deref for JPrimitiveArray<'local, T> {
43     type Target = JObject<'local>;
44 
deref(&self) -> &Self::Target45     fn deref(&self) -> &Self::Target {
46         &self.obj
47     }
48 }
49 
50 impl<'local, T: TypeArray> From<JPrimitiveArray<'local, T>> for JObject<'local> {
from(other: JPrimitiveArray<'local, T>) -> JObject51     fn from(other: JPrimitiveArray<'local, T>) -> JObject {
52         other.obj
53     }
54 }
55 
56 /// This conversion assumes that the `JObject` is a pointer to a class object.
57 impl<'local, T: TypeArray> From<JObject<'local>> for JPrimitiveArray<'local, T> {
from(other: JObject) -> Self58     fn from(other: JObject) -> Self {
59         unsafe { Self::from_raw(other.into_raw()) }
60     }
61 }
62 
63 /// This conversion assumes that the `JObject` is a pointer to a class object.
64 impl<'local, 'obj_ref, T: TypeArray> From<&'obj_ref JObject<'local>>
65     for &'obj_ref JPrimitiveArray<'local, T>
66 {
from(other: &'obj_ref JObject<'local>) -> Self67     fn from(other: &'obj_ref JObject<'local>) -> Self {
68         // Safety: `JPrimitiveArray` is `repr(transparent)` around `JObject`.
69         unsafe { &*(other as *const JObject<'local> as *const JPrimitiveArray<'local, T>) }
70     }
71 }
72 
73 impl<'local, T: TypeArray> std::default::Default for JPrimitiveArray<'local, T> {
default() -> Self74     fn default() -> Self {
75         Self {
76             obj: JObject::null(),
77             lifetime: PhantomData,
78         }
79     }
80 }
81 
82 impl<'local, T: TypeArray> JPrimitiveArray<'local, T> {
83     /// Creates a [`JPrimitiveArray`] that wraps the given `raw` [`jarray`]
84     ///
85     /// # Safety
86     ///
87     /// `raw` may be a null pointer. If `raw` is not a null pointer, then:
88     ///
89     /// * `raw` must be a valid raw JNI local reference.
90     /// * There must not be any other `JObject` representing the same local reference.
91     /// * The lifetime `'local` must not outlive the local reference frame that the local reference
92     ///   was created in.
from_raw(raw: jarray) -> Self93     pub unsafe fn from_raw(raw: jarray) -> Self {
94         Self {
95             obj: JObject::from_raw(raw as jobject),
96             lifetime: PhantomData,
97         }
98     }
99 
100     /// Unwrap to the raw jni type.
into_raw(self) -> jarray101     pub fn into_raw(self) -> jarray {
102         self.obj.into_raw() as jarray
103     }
104 }
105 
106 /// Lifetime'd representation of a [`crate::sys::jbooleanArray`] which wraps a [`JObject`] reference
107 pub type JBooleanArray<'local> = JPrimitiveArray<'local, crate::sys::jboolean>;
108 
109 /// Lifetime'd representation of a [`crate::sys::jbyteArray`] which wraps a [`JObject`] reference
110 pub type JByteArray<'local> = JPrimitiveArray<'local, crate::sys::jbyte>;
111 
112 /// Lifetime'd representation of a [`crate::sys::jcharArray`] which wraps a [`JObject`] reference
113 pub type JCharArray<'local> = JPrimitiveArray<'local, crate::sys::jchar>;
114 
115 /// Lifetime'd representation of a [`crate::sys::jshortArray`] which wraps a [`JObject`] reference
116 pub type JShortArray<'local> = JPrimitiveArray<'local, crate::sys::jshort>;
117 
118 /// Lifetime'd representation of a [`crate::sys::jintArray`] which wraps a [`JObject`] reference
119 pub type JIntArray<'local> = JPrimitiveArray<'local, crate::sys::jint>;
120 
121 /// Lifetime'd representation of a [`crate::sys::jlongArray`] which wraps a [`JObject`] reference
122 pub type JLongArray<'local> = JPrimitiveArray<'local, crate::sys::jlong>;
123 
124 /// Lifetime'd representation of a [`crate::sys::jfloatArray`] which wraps a [`JObject`] reference
125 pub type JFloatArray<'local> = JPrimitiveArray<'local, crate::sys::jfloat>;
126 
127 /// Lifetime'd representation of a [`crate::sys::jdoubleArray`] which wraps a [`JObject`] reference
128 pub type JDoubleArray<'local> = JPrimitiveArray<'local, crate::sys::jdouble>;
129 
130 /// Trait to access the raw `jarray` pointer for types that wrap an array reference
131 ///
132 /// # Safety
133 ///
134 /// Implementing this trait will allow a type to be passed to [`JNIEnv::get_array_length()`]
135 /// or other JNI APIs that only work with a valid reference to an array (or `null`)
136 ///
137 pub unsafe trait AsJArrayRaw<'local>: AsRef<JObject<'local>> {
138     /// Returns the raw JNI pointer as a `jarray`
as_jarray_raw(&self) -> jarray139     fn as_jarray_raw(&self) -> jarray {
140         self.as_ref().as_raw() as jarray
141     }
142 }
143 
144 unsafe impl<'local, T: TypeArray> AsJArrayRaw<'local> for JPrimitiveArray<'local, T> {}
145