1
1
use std:: marker:: PhantomData ;
2
2
use std:: ops:: { Bound , RangeBounds } ;
3
3
use std:: ptr:: null_mut;
4
+ use std:: sync:: OnceLock ;
4
5
5
6
use jni_sys:: * ;
6
7
7
- use crate :: { AsArg , Env , JniType , Local , Ref , ReferenceType , ThrowableType } ;
8
+ use crate :: { AsArg , Env , JClass , JniType , Local , Ref , ReferenceType , ThrowableType } ;
8
9
9
10
/// A Java Array of some POD-like type such as bool, jbyte, jchar, jshort, jint, jlong, jfloat, or jdouble.
10
11
///
43
44
array
44
45
}
45
46
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
+
46
52
/// Uses env.GetArrayLength + env.Get{Type}ArrayRegion to read the contents of the java array from range into a new Vec.
47
53
fn get_region_as_vec ( self : & Ref < ' _ , Self > , range : impl RangeBounds < usize > ) -> Vec < T > {
48
54
let len = self . len ( ) ;
@@ -80,7 +86,12 @@ macro_rules! primitive_array {
80
86
/// A [PrimitiveArray] implementation.
81
87
pub enum $name { }
82
88
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
+ }
84
95
unsafe impl JniType for $name {
85
96
fn static_with_jni_type<R >( callback: impl FnOnce ( & str ) -> R ) -> R {
86
97
callback( $type_str)
@@ -89,7 +100,7 @@ macro_rules! primitive_array {
89
100
90
101
impl PrimitiveArray <$type> for $name {
91
102
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
93
104
let size = size as jsize;
94
105
let jnienv = env. as_raw( ) ;
95
106
unsafe {
@@ -116,8 +127,8 @@ macro_rules! primitive_array {
116
127
}
117
128
118
129
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
121
132
let self_len = self . len( ) as jsize;
122
133
let elements_len = elements. len( ) as jsize;
123
134
@@ -139,8 +150,8 @@ macro_rules! primitive_array {
139
150
}
140
151
141
152
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
144
155
let self_len = self . len( ) as jsize;
145
156
let elements_len = elements. len( ) as jsize;
146
157
@@ -178,7 +189,12 @@ primitive_array! { DoubleArray, "[D\0", jdouble { NewDoubleArray SetDoubleArra
178
189
/// See also [PrimitiveArray] for arrays of reference types.
179
190
pub struct ObjectArray < T : ReferenceType , E : ThrowableType > ( core:: convert:: Infallible , PhantomData < ( T , E ) > ) ;
180
191
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
+ }
182
198
183
199
unsafe impl < T : ReferenceType , E : ThrowableType > JniType for ObjectArray < T , E > {
184
200
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> {
188
204
189
205
impl < T : ReferenceType , E : ThrowableType > ObjectArray < T , E > {
190
206
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 ( ) ;
193
209
let size = size as jsize ;
194
210
195
211
let object = unsafe {
@@ -210,10 +226,7 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
210
226
}
211
227
}
212
228
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 > {
217
230
let size = elements. len ( ) ;
218
231
let array = Self :: new ( env, size) ;
219
232
let env = array. env ( ) . as_raw ( ) ;
@@ -229,9 +242,13 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
229
242
unsafe { ( ( * * env) . v1_2 . GetArrayLength ) ( env, self . as_raw ( ) ) as usize }
230
243
}
231
244
245
+ pub fn is_empty ( self : & Ref < ' _ , Self > ) -> bool {
246
+ self . len ( ) == 0
247
+ }
248
+
232
249
/// XXX: Expose this via std::ops::Index
233
250
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?
235
252
let index = index as jsize ;
236
253
let env = self . env ( ) ;
237
254
let result = unsafe {
@@ -248,7 +265,7 @@ impl<T: ReferenceType, E: ThrowableType> ObjectArray<T, E> {
248
265
249
266
/// XXX: I don't think there's a way to expose this via std::ops::IndexMut sadly?
250
267
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?
252
269
let index = index as jsize ;
253
270
let env = self . env ( ) ;
254
271
unsafe {
0 commit comments