11use std:: marker:: PhantomData ;
22use std:: ops:: { Bound , RangeBounds } ;
33use std:: ptr:: null_mut;
4+ use std:: sync:: OnceLock ;
45
56use jni_sys:: * ;
67
7- use crate :: { AsArg , Env , JniType , Local , Ref , ReferenceType , ThrowableType } ;
8+ use crate :: { AsArg , Env , JClass , JniType , Local , Ref , ReferenceType , ThrowableType } ;
89
910/// A Java Array of some POD-like type such as bool, jbyte, jchar, jshort, jint, jlong, jfloat, or jdouble.
1011///
4344 array
4445 }
4546
47+ /// Uses env.GetArrayLength to get the length of the java array, returns true if it is 0.
48+ fn is_empty ( self : & Ref < ' _ , Self > ) -> bool {
49+ self . len ( ) == 0
50+ }
51+
4652 /// Uses env.GetArrayLength + env.Get{Type}ArrayRegion to read the contents of the java array from range into a new Vec.
4753 fn get_region_as_vec ( self : & Ref < ' _ , Self > , range : impl RangeBounds < usize > ) -> Vec < T > {
4854 let len = self . len ( ) ;
@@ -80,7 +86,12 @@ macro_rules! primitive_array {
8086 /// A [PrimitiveArray] implementation.
8187 pub enum $name { }
8288
83- unsafe impl ReferenceType for $name { }
89+ unsafe impl ReferenceType for $name {
90+ fn jni_get_class( env: Env ) -> & ' static JClass {
91+ static CLASS_CACHE : OnceLock <JClass > = OnceLock :: new( ) ;
92+ CLASS_CACHE . get_or_init( || Self :: static_with_jni_type( |t| unsafe { env. require_class( t) } ) )
93+ }
94+ }
8495 unsafe impl JniType for $name {
8596 fn static_with_jni_type<R >( callback: impl FnOnce ( & str ) -> R ) -> R {
8697 callback( $type_str)
@@ -89,7 +100,7 @@ macro_rules! primitive_array {
89100
90101 impl PrimitiveArray <$type> for $name {
91102 fn new<' env>( env: Env <' env>, size: usize ) -> Local <' env, Self > {
92- assert!( size <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
103+ assert!( size <= i32 :: MAX as usize ) ; // jsize == jint == i32
93104 let size = size as jsize;
94105 let jnienv = env. as_raw( ) ;
95106 unsafe {
@@ -116,8 +127,8 @@ macro_rules! primitive_array {
116127 }
117128
118129 fn get_region( self : & Ref <' _, Self >, start: usize , elements: & mut [ $type] ) {
119- assert!( start <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
120- assert!( elements. len( ) <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
130+ assert!( start <= i32 :: MAX as usize ) ; // jsize == jint == i32
131+ assert!( elements. len( ) <= i32 :: MAX as usize ) ; // jsize == jint == i32
121132 let self_len = self . len( ) as jsize;
122133 let elements_len = elements. len( ) as jsize;
123134
@@ -139,8 +150,8 @@ macro_rules! primitive_array {
139150 }
140151
141152 fn set_region( self : & Ref <' _, Self >, start: usize , elements: & [ $type] ) {
142- assert!( start <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
143- assert!( elements. len( ) <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
153+ assert!( start <= i32 :: MAX as usize ) ; // jsize == jint == i32
154+ assert!( elements. len( ) <= i32 :: MAX as usize ) ; // jsize == jint == i32
144155 let self_len = self . len( ) as jsize;
145156 let elements_len = elements. len( ) as jsize;
146157
@@ -178,7 +189,12 @@ primitive_array! { DoubleArray, "[D\0", jdouble { NewDoubleArray SetDoubleArra
178189/// See also [PrimitiveArray] for arrays of reference types.
179190pub struct ObjectArray < T : ReferenceType , E : ThrowableType > ( core:: convert:: Infallible , PhantomData < ( T , E ) > ) ;
180191
181- unsafe impl < T : ReferenceType , E : ThrowableType > ReferenceType for ObjectArray < T , E > { }
192+ unsafe impl < T : ReferenceType , E : ThrowableType > ReferenceType for ObjectArray < T , E > {
193+ fn jni_get_class ( env : Env ) -> & ' static JClass {
194+ static CLASS_CACHE : OnceLock < JClass > = OnceLock :: new ( ) ;
195+ CLASS_CACHE . get_or_init ( || Self :: static_with_jni_type ( |t| unsafe { env. require_class ( t) } ) )
196+ }
197+ }
182198
183199unsafe impl < T : ReferenceType , E : ThrowableType > JniType for ObjectArray < T , E > {
184200 fn static_with_jni_type < R > ( callback : impl FnOnce ( & str ) -> R ) -> R {
@@ -188,8 +204,8 @@ unsafe impl<T: ReferenceType, E: ThrowableType> JniType for ObjectArray<T, E> {
188204
189205impl < T : ReferenceType , E : ThrowableType > ObjectArray < T , E > {
190206 pub fn new < ' env > ( env : Env < ' env > , size : usize ) -> Local < ' env , Self > {
191- assert ! ( size <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32
192- let class = T :: static_with_jni_type ( |t| unsafe { env. require_class ( t ) } ) ;
207+ assert ! ( size <= i32 :: MAX as usize ) ; // jsize == jint == i32
208+ let class = T :: jni_get_class ( env) . as_raw ( ) ;
193209 let size = size as jsize ;
194210
195211 let object = unsafe {
@@ -210,10 +226,7 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
210226 }
211227 }
212228
213- pub fn new_from < ' env > (
214- env : Env < ' env > ,
215- elements : impl ExactSizeIterator + Iterator < Item = impl AsArg < T > > ,
216- ) -> Local < ' env , Self > {
229+ pub fn new_from < ' env > ( env : Env < ' env > , elements : impl ExactSizeIterator < Item = impl AsArg < T > > ) -> Local < ' env , Self > {
217230 let size = elements. len ( ) ;
218231 let array = Self :: new ( env, size) ;
219232 let env = array. env ( ) . as_raw ( ) ;
@@ -229,9 +242,13 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
229242 unsafe { ( ( * * env) . v1_2 . GetArrayLength ) ( env, self . as_raw ( ) ) as usize }
230243 }
231244
245+ pub fn is_empty ( self : & Ref < ' _ , Self > ) -> bool {
246+ self . len ( ) == 0
247+ }
248+
232249 /// XXX: Expose this via std::ops::Index
233250 pub fn get < ' env > ( self : & Ref < ' env , Self > , index : usize ) -> Result < Option < Local < ' env , T > > , Local < ' env , E > > {
234- assert ! ( index <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32 XXX: Should maybe be treated as an exception?
251+ assert ! ( index <= i32 :: MAX as usize ) ; // jsize == jint == i32 XXX: Should maybe be treated as an exception?
235252 let index = index as jsize ;
236253 let env = self . env ( ) ;
237254 let result = unsafe {
@@ -248,7 +265,7 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
248265
249266 /// XXX: I don't think there's a way to expose this via std::ops::IndexMut sadly?
250267 pub fn set < ' env > ( self : & Ref < ' env , Self > , index : usize , value : impl AsArg < T > ) -> Result < ( ) , Local < ' env , E > > {
251- assert ! ( index <= std :: i32 :: MAX as usize ) ; // jsize == jint == i32 XXX: Should maybe be treated as an exception?
268+ assert ! ( index <= i32 :: MAX as usize ) ; // jsize == jint == i32 XXX: Should maybe be treated as an exception?
252269 let index = index as jsize ;
253270 let env = self . env ( ) ;
254271 unsafe {
0 commit comments