1use super::*;
2
3use std::marker::*;
4use std::ops::*;
5
6pub trait PrimitiveArray<T> where Self : Sized + AsValidJObjectAndEnv, T : Clone + Default {
38 fn new<'env>(env: &'env Env, size: usize) -> Local<'env, Self>;
40
41 fn len(&self) -> usize;
43
44 fn get_region(&self, start: usize, elements: &mut [T]);
46
47 fn set_region(&self, start: usize, elements: &[T]);
49
50 fn from<'env>(env: &'env Env, elements: &[T]) -> Local<'env, Self> {
52 let array = Self::new(env, elements.len());
53 array.set_region(0, elements);
54 array
55 }
56
57 fn get_region_as_vec(&self, range: impl RangeBounds<usize>) -> Vec<T> {
59 let len = self.len();
60
61 let start = match range.start_bound() {
62 Bound::Unbounded => 0,
63 Bound::Included(n) => *n,
64 Bound::Excluded(n) => *n+1,
65 };
66
67 let end = match range.end_bound() {
68 Bound::Unbounded => len,
69 Bound::Included(n) => *n+1,
70 Bound::Excluded(n) => *n,
71 };
72
73 assert!(start <= end);
74 assert!(end <= len);
75 let vec_len = end - start;
76
77 let mut vec = Vec::new();
78 vec.resize(vec_len, Default::default());
79 self.get_region(start, &mut vec[..]);
80 vec
81 }
82
83 fn as_vec(&self) -> Vec<T> {
85 self.get_region_as_vec(0..self.len())
86 }
87}
88
89#[test] fn bool_ffi_assumptions_test() {
94 use std::mem::*;
95
96 assert_eq!(size_of::<jboolean>(), 1); assert_eq!(size_of::<bool>(), 1); assert_eq!(unsafe { std::mem::transmute::<bool, u8>(true ) }, JNI_TRUE );
102 assert_eq!(unsafe { std::mem::transmute::<bool, u8>(false) }, JNI_FALSE);
103}
104
105macro_rules! primitive_array {
106 (#[repr(transparent)] pub struct $name:ident = $type_str:expr, $type:ident { $new_array:ident $set_region:ident $get_region:ident } ) => {
107 #[repr(transparent)] pub struct $name(ObjectAndEnv);
109
110 unsafe impl AsValidJObjectAndEnv for $name {}
111 unsafe impl AsJValue for $name { fn as_jvalue(&self) -> jni_sys::jvalue { jni_sys::jvalue { l: self.0.object } } }
112 unsafe impl JniType for $name { fn static_with_jni_type<R>(callback: impl FnOnce(&str) -> R) -> R { callback($type_str) } }
113
114 impl PrimitiveArray<$type> for $name {
115 fn new<'env>(env: &'env Env, size: usize) -> Local<'env, Self> {
116 assert!(size <= std::i32::MAX as usize); let size = size as jsize;
118 let env = env.as_jni_env();
119 unsafe {
120 let object = (**env).$new_array.unwrap()(env, size);
121 let exception = (**env).ExceptionOccurred.unwrap()(env);
122 assert!(exception.is_null()); Local::from_env_object(env, object)
124 }
125 }
126
127 fn from<'env>(env: &'env Env, elements: &[$type]) -> Local<'env, Self> {
128 let array = Self::new(env, elements.len());
129 let size = elements.len() as jsize;
130 let env = array.0.env as *mut JNIEnv;
131 let object = array.0.object;
132 unsafe {
133 (**env).$set_region.unwrap()(env, object, 0, size, elements.as_ptr() as *const _);
134 }
135 array
136 }
137
138 fn len(&self) -> usize {
139 unsafe { (**self.0.env).GetArrayLength.unwrap()(self.0.env as *mut _, self.0.object) as usize }
140 }
141
142 fn get_region(&self, start: usize, elements: &mut [$type]) {
143 assert!(start <= std::i32::MAX as usize); assert!(elements.len() <= std::i32::MAX as usize); let self_len = self.len() as jsize;
146 let elements_len = elements.len() as jsize;
147
148 let start = start as jsize;
149 let end = start + elements_len;
150 assert!(start <= end);
151 assert!(end <= self_len);
152
153 unsafe { (**self.0.env).$get_region.unwrap()(self.0.env as *mut _, self.0.object, start, elements_len, elements.as_mut_ptr() as *mut _) };
154 }
155
156 fn set_region(&self, start: usize, elements: &[$type]) {
157 assert!(start <= std::i32::MAX as usize); assert!(elements.len() <= std::i32::MAX as usize); let self_len = self.len() as jsize;
160 let elements_len = elements.len() as jsize;
161
162 let start = start as jsize;
163 let end = start + elements_len;
164 assert!(start <= end);
165 assert!(end <= self_len);
166
167 unsafe { (**self.0.env).$set_region.unwrap()(self.0.env as *mut _, self.0.object, start, elements_len, elements.as_ptr() as *const _) };
168 }
169 }
170 };
171}
172
173primitive_array! { #[repr(transparent)] pub struct BooleanArray = "[Z\0", bool { NewBooleanArray SetBooleanArrayRegion GetBooleanArrayRegion } }
174primitive_array! { #[repr(transparent)] pub struct ByteArray = "[B\0", jbyte { NewByteArray SetByteArrayRegion GetByteArrayRegion } }
175primitive_array! { #[repr(transparent)] pub struct CharArray = "[C\0", jchar { NewCharArray SetCharArrayRegion GetCharArrayRegion } }
176primitive_array! { #[repr(transparent)] pub struct ShortArray = "[S\0", jshort { NewShortArray SetShortArrayRegion GetShortArrayRegion } }
177primitive_array! { #[repr(transparent)] pub struct IntArray = "[I\0", jint { NewIntArray SetIntArrayRegion GetIntArrayRegion } }
178primitive_array! { #[repr(transparent)] pub struct LongArray = "[J\0", jlong { NewLongArray SetLongArrayRegion GetLongArrayRegion } }
179primitive_array! { #[repr(transparent)] pub struct FloatArray = "[F\0", jfloat { NewFloatArray SetFloatArrayRegion GetFloatArrayRegion } }
180primitive_array! { #[repr(transparent)] pub struct DoubleArray = "[D\0", jdouble { NewDoubleArray SetDoubleArrayRegion GetDoubleArrayRegion } }
181
182#[repr(transparent)]
189pub struct ObjectArray<T: AsValidJObjectAndEnv, E: ThrowableType>(ObjectAndEnv, PhantomData<(T,E)>);
190
191unsafe impl<T: AsValidJObjectAndEnv, E: ThrowableType> AsValidJObjectAndEnv for ObjectArray<T, E> {}
192
193unsafe impl<T: AsValidJObjectAndEnv, E: ThrowableType> JniType for ObjectArray<T, E> {
194 fn static_with_jni_type<R>(callback: impl FnOnce(&str) -> R) -> R {
195 T::static_with_jni_type(|inner| callback(format!("[{}", inner).as_str()))
196 }
197}
198
199unsafe impl<T: AsValidJObjectAndEnv, E: ThrowableType> AsJValue for ObjectArray<T, E> {
200 fn as_jvalue(&self) -> jni_sys::jvalue {
201 jni_sys::jvalue { l: self.0.object }
202 }
203}
204
205impl<T: AsValidJObjectAndEnv, E: ThrowableType> ObjectArray<T, E> {
206 pub fn new<'env>(env: &'env Env, size: usize) -> Local<'env, Self> {
207 assert!(size <= std::i32::MAX as usize); let class = Self::static_with_jni_type(|t| unsafe { env.require_class(t) });
209 let size = size as jsize;
210 let env = env.as_jni_env();
211 unsafe {
212 let fill = null_mut();
213 let object = (**env).NewObjectArray.unwrap()(env, size, class, fill);
214 let exception = (**env).ExceptionOccurred.unwrap()(env);
215 assert!(exception.is_null()); Local::from_env_object(env, object)
217 }
218 }
219
220 pub fn iter<'env>(&'env self) -> ObjectArrayIter<'env, T, E> {
221 ObjectArrayIter {
222 array: self,
223 index: 0,
224 length: self.len(),
225 }
226 }
227
228 pub fn from<'env>(env: &'env Env, elements: impl 'env + ExactSizeIterator + Iterator<Item = impl Into<Option<&'env T>>>) -> Local<'env, Self> {
229 let size = elements.len();
230 let array = Self::new(env, size);
231 let env = array.0.env as *mut JNIEnv;
232 let this = array.0.object;
233 let set = unsafe { (**env) }.SetObjectArrayElement.unwrap();
234
235 for (index, element) in elements.enumerate() {
236 assert!(index < size); let value = element.into().map(|v| unsafe { AsJValue::as_jvalue(v.into()).l }).unwrap_or(null_mut());
238 unsafe { set(env, this, index as jsize, value) };
239 }
240 array
241 }
242
243 pub fn len(&self) -> usize {
244 unsafe { (**self.0.env).GetArrayLength.unwrap()(self.0.env as *mut _, self.0.object) as usize }
245 }
246
247 pub fn get<'env>(&'env self, index: usize) -> Result<Option<Local<'env, T>>, Local<'env, E>> {
249 assert!(index <= std::i32::MAX as usize); let index = index as jsize;
251 let env = self.0.env as *mut JNIEnv;
252 let this = self.0.object;
253 unsafe {
254 let result = (**env).GetObjectArrayElement.unwrap()(env, this, index);
255 let exception = (**env).ExceptionOccurred.unwrap()(env);
256 if !exception.is_null() {
257 (**env).ExceptionClear.unwrap()(env);
258 Err(Local::from_env_object(env, exception))
259 } else if result.is_null() {
260 Ok(None)
261 } else {
262 Ok(Some(Local::from_env_object(env, result)))
263 }
264 }
265 }
266
267 pub fn set<'env>(&'env self, index: usize, value: impl Into<Option<&'env T>>) -> Result<(), Local<'env, E>> {
269 assert!(index <= std::i32::MAX as usize); let value = value.into().map(|v| unsafe { AsJValue::as_jvalue(v.into()).l }).unwrap_or(null_mut());
271 let index = index as jsize;
272 let env = self.0.env as *mut JNIEnv;
273 let this = self.0.object;
274 unsafe {
275 (**env).SetObjectArrayElement.unwrap()(env, this, index, value);
276 let exception = (**env).ExceptionOccurred.unwrap()(env);
277 if !exception.is_null() {
278 (**env).ExceptionClear.unwrap()(env);
279 Err(Local::from_env_object(env, exception))
280 } else {
281 Ok(())
282 }
283 }
284 }
285}
286
287
288
289pub struct ObjectArrayIter<'env, T: AsValidJObjectAndEnv, E: ThrowableType> {
290 array: &'env ObjectArray<T, E>,
291 index: usize,
292 length: usize,
293}
294
295impl<'env, T: AsValidJObjectAndEnv, E: ThrowableType> Iterator for ObjectArrayIter<'env, T, E> {
296 type Item = Option<Local<'env, T>>;
297 fn next(&mut self) -> Option<Self::Item> {
298 let index = self.index;
299 if index < self.length {
300 self.index = index + 1;
301 Some(self.array.get(index).unwrap_or(None))
302 } else {
303 None
304 }
305 }
306}