Skip to content

Commit b0258b3

Browse files
committed
Implemented new function for creating Java lists, using try_from for the basic types instead of &str
1 parent d203b68 commit b0258b3

File tree

4 files changed

+166
-87
lines changed

4 files changed

+166
-87
lines changed

rust/src/api/invocation_arg.rs

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use crate::api::{CLASS_BOOLEAN, CLASS_BYTE, CLASS_CHARACTER, CLASS_DOUBLE, CLASS_FLOAT, CLASS_INTEGER, CLASS_LIST, CLASS_LONG, CLASS_SHORT, CLASS_STRING, Jvm, Null};
15+
use std::any::Any;
1616
use std::convert::TryFrom;
17+
use std::ptr;
18+
19+
use jni_sys::{JNIEnv, jobject};
1720
use serde::Serialize;
1821
use serde_json;
19-
use std::any::Any;
20-
use jni_sys::{JNIEnv, jobject};
21-
use std::ptr;
22+
2223
use crate::{cache, errors, jni_utils, utils};
24+
use crate::api::{JavaClass, Jvm, Null};
2325
use crate::api::instance::Instance;
2426

2527
/// Struct that carries an argument that is used for method invocations in Java.
@@ -177,19 +179,19 @@ impl InvocationArg {
177179

178180
/// Creates an InvocationArg that contains null
179181
pub fn create_null(null: Null) -> errors::Result<InvocationArg> {
180-
let class_name = match null {
181-
Null::String => CLASS_STRING,
182-
Null::Boolean => CLASS_BOOLEAN,
183-
Null::Byte => CLASS_BYTE,
184-
Null::Character => CLASS_CHARACTER,
185-
Null::Short => CLASS_SHORT,
186-
Null::Integer => CLASS_INTEGER,
187-
Null::Long => CLASS_LONG,
188-
Null::Float => CLASS_FLOAT,
189-
Null::Double => CLASS_DOUBLE,
190-
Null::List => CLASS_LIST,
191-
Null::Of(class_name) => class_name,
192-
};
182+
let class_name: &str = match null {
183+
Null::String => JavaClass::String,
184+
Null::Boolean => JavaClass::Boolean,
185+
Null::Byte => JavaClass::Byte,
186+
Null::Character => JavaClass::Character,
187+
Null::Short => JavaClass::Short,
188+
Null::Integer => JavaClass::Integer,
189+
Null::Long => JavaClass::Long,
190+
Null::Float => JavaClass::Float,
191+
Null::Double => JavaClass::Double,
192+
Null::List => JavaClass::List,
193+
Null::Of(class_name) => JavaClass::Of(class_name),
194+
}.into();
193195
Ok(InvocationArg::RustBasic {
194196
instance: Instance::new(ptr::null_mut(), class_name)?,
195197
class_name: class_name.to_string(),
@@ -220,7 +222,7 @@ impl<'a> TryFrom<Null<'a>> for InvocationArg {
220222
impl TryFrom<String> for InvocationArg {
221223
type Error = errors::J4RsError;
222224
fn try_from(arg: String) -> errors::Result<InvocationArg> {
223-
InvocationArg::new_2(&arg, CLASS_STRING, cache::get_thread_local_env()?)
225+
InvocationArg::new_2(&arg, JavaClass::String.into(), cache::get_thread_local_env()?)
224226
}
225227
}
226228

@@ -236,7 +238,7 @@ impl<'a> TryFrom<&'a [String]> for InvocationArg {
236238
impl<'a> TryFrom<&'a str> for InvocationArg {
237239
type Error = errors::J4RsError;
238240
fn try_from(arg: &'a str) -> errors::Result<InvocationArg> {
239-
InvocationArg::new_2(&arg.to_string(), CLASS_STRING, cache::get_thread_local_env()?)
241+
InvocationArg::new_2(&arg.to_string(), JavaClass::String.into(), cache::get_thread_local_env()?)
240242
}
241243
}
242244

@@ -252,7 +254,7 @@ impl<'a> TryFrom<&'a [&'a str]> for InvocationArg {
252254
impl TryFrom<bool> for InvocationArg {
253255
type Error = errors::J4RsError;
254256
fn try_from(arg: bool) -> errors::Result<InvocationArg> {
255-
InvocationArg::new_2(&arg, CLASS_BOOLEAN, cache::get_thread_local_env()?)
257+
InvocationArg::new_2(&arg, JavaClass::Boolean.into(), cache::get_thread_local_env()?)
256258
}
257259
}
258260

@@ -268,7 +270,7 @@ impl<'a> TryFrom<&'a [bool]> for InvocationArg {
268270
impl TryFrom<i8> for InvocationArg {
269271
type Error = errors::J4RsError;
270272
fn try_from(arg: i8) -> errors::Result<InvocationArg> {
271-
InvocationArg::new_2(&arg, CLASS_BYTE, cache::get_thread_local_env()?)
273+
InvocationArg::new_2(&arg, JavaClass::Byte.into(), cache::get_thread_local_env()?)
272274
}
273275
}
274276

@@ -284,7 +286,7 @@ impl<'a> TryFrom<&'a [i8]> for InvocationArg {
284286
impl TryFrom<char> for InvocationArg {
285287
type Error = errors::J4RsError;
286288
fn try_from(arg: char) -> errors::Result<InvocationArg> {
287-
InvocationArg::new_2(&arg, CLASS_CHARACTER, cache::get_thread_local_env()?)
289+
InvocationArg::new_2(&arg, JavaClass::Character.into(), cache::get_thread_local_env()?)
288290
}
289291
}
290292

@@ -300,7 +302,7 @@ impl<'a> TryFrom<&'a [char]> for InvocationArg {
300302
impl TryFrom<i16> for InvocationArg {
301303
type Error = errors::J4RsError;
302304
fn try_from(arg: i16) -> errors::Result<InvocationArg> {
303-
InvocationArg::new_2(&arg, CLASS_SHORT, cache::get_thread_local_env()?)
305+
InvocationArg::new_2(&arg, JavaClass::Short.into(), cache::get_thread_local_env()?)
304306
}
305307
}
306308

@@ -316,7 +318,7 @@ impl<'a> TryFrom<&'a [i16]> for InvocationArg {
316318
impl TryFrom<i32> for InvocationArg {
317319
type Error = errors::J4RsError;
318320
fn try_from(arg: i32) -> errors::Result<InvocationArg> {
319-
InvocationArg::new_2(&arg, CLASS_INTEGER, cache::get_thread_local_env()?)
321+
InvocationArg::new_2(&arg, JavaClass::Integer.into(), cache::get_thread_local_env()?)
320322
}
321323
}
322324

@@ -332,7 +334,7 @@ impl<'a> TryFrom<&'a [i32]> for InvocationArg {
332334
impl TryFrom<i64> for InvocationArg {
333335
type Error = errors::J4RsError;
334336
fn try_from(arg: i64) -> errors::Result<InvocationArg> {
335-
InvocationArg::new_2(&arg, CLASS_LONG, cache::get_thread_local_env()?)
337+
InvocationArg::new_2(&arg, JavaClass::Long.into(), cache::get_thread_local_env()?)
336338
}
337339
}
338340

@@ -348,7 +350,7 @@ impl<'a> TryFrom<&'a [i64]> for InvocationArg {
348350
impl TryFrom<f32> for InvocationArg {
349351
type Error = errors::J4RsError;
350352
fn try_from(arg: f32) -> errors::Result<InvocationArg> {
351-
InvocationArg::new_2(&arg, CLASS_FLOAT, cache::get_thread_local_env()?)
353+
InvocationArg::new_2(&arg, JavaClass::Float.into(), cache::get_thread_local_env()?)
352354
}
353355
}
354356

@@ -364,7 +366,7 @@ impl<'a> TryFrom<&'a [f32]> for InvocationArg {
364366
impl TryFrom<f64> for InvocationArg {
365367
type Error = errors::J4RsError;
366368
fn try_from(arg: f64) -> errors::Result<InvocationArg> {
367-
InvocationArg::new_2(&arg, CLASS_DOUBLE, cache::get_thread_local_env()?)
369+
InvocationArg::new_2(&arg, JavaClass::Double.into(), cache::get_thread_local_env()?)
368370
}
369371
}
370372

@@ -377,91 +379,94 @@ impl<'a> TryFrom<&'a [f64]> for InvocationArg {
377379
}
378380
}
379381

380-
impl<'a, T: 'static> TryFrom<(&'a [T], &'a str)> for InvocationArg where T: Serialize {
381-
type Error = errors::J4RsError;
382-
fn try_from(vec: (&'a [T], &'a str)) -> errors::Result<InvocationArg> {
383-
let (vec, elements_class_name) = vec;
384-
let jni_env = cache::get_thread_local_env()?;
385-
let args: errors::Result<Vec<InvocationArg>> = vec.iter().map(|elem| InvocationArg::new_2(elem, elements_class_name, jni_env)).collect();
386-
let res = Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
387-
Ok(InvocationArg::from(res?))
388-
}
389-
}
390-
391382
impl TryFrom<()> for InvocationArg {
392383
type Error = errors::J4RsError;
393384
fn try_from(arg: ()) -> errors::Result<InvocationArg> {
394-
InvocationArg::new_2(&arg, "void", cache::get_thread_local_env()?)
385+
InvocationArg::new_2(&arg, JavaClass::Void.into(), cache::get_thread_local_env()?)
395386
}
396387
}
397388

398389
impl<'a> TryFrom<&'a String> for InvocationArg {
399390
type Error = errors::J4RsError;
400391
fn try_from(arg: &'a String) -> errors::Result<InvocationArg> {
401-
InvocationArg::new_2(arg, CLASS_STRING, cache::get_thread_local_env()?)
392+
InvocationArg::new_2(arg, JavaClass::String.into(), cache::get_thread_local_env()?)
402393
}
403394
}
404395

405396
impl<'a> TryFrom<&'a bool> for InvocationArg {
406397
type Error = errors::J4RsError;
407398
fn try_from(arg: &'a bool) -> errors::Result<InvocationArg> {
408-
InvocationArg::new_2(arg, CLASS_BOOLEAN, cache::get_thread_local_env()?)
399+
InvocationArg::new_2(arg, JavaClass::Boolean.into(), cache::get_thread_local_env()?)
409400
}
410401
}
411402

412403
impl<'a> TryFrom<&'a i8> for InvocationArg {
413404
type Error = errors::J4RsError;
414405
fn try_from(arg: &'a i8) -> errors::Result<InvocationArg> {
415-
InvocationArg::new_2(arg, CLASS_BYTE, cache::get_thread_local_env()?)
406+
InvocationArg::new_2(arg, JavaClass::Byte.into(), cache::get_thread_local_env()?)
416407
}
417408
}
418409

419410
impl<'a> TryFrom<&'a char> for InvocationArg {
420411
type Error = errors::J4RsError;
421412
fn try_from(arg: &'a char) -> errors::Result<InvocationArg> {
422-
InvocationArg::new_2(arg, CLASS_CHARACTER, cache::get_thread_local_env()?)
413+
InvocationArg::new_2(arg, JavaClass::Character.into(), cache::get_thread_local_env()?)
423414
}
424415
}
425416

426417
impl<'a> TryFrom<&'a i16> for InvocationArg {
427418
type Error = errors::J4RsError;
428419
fn try_from(arg: &'a i16) -> errors::Result<InvocationArg> {
429-
InvocationArg::new_2(arg, CLASS_SHORT, cache::get_thread_local_env()?)
420+
InvocationArg::new_2(arg, JavaClass::Short.into(), cache::get_thread_local_env()?)
430421
}
431422
}
432423

433424
impl<'a, 'b> TryFrom<&'a i32> for InvocationArg {
434425
type Error = errors::J4RsError;
435426
fn try_from(arg: &'a i32) -> errors::Result<InvocationArg> {
436-
InvocationArg::new_2(arg, CLASS_INTEGER, cache::get_thread_local_env()?)
427+
InvocationArg::new_2(arg, JavaClass::Integer.into(), cache::get_thread_local_env()?)
437428
}
438429
}
439430

440431
impl<'a> TryFrom<&'a i64> for InvocationArg {
441432
type Error = errors::J4RsError;
442433
fn try_from(arg: &'a i64) -> errors::Result<InvocationArg> {
443-
InvocationArg::new_2(arg, CLASS_LONG, cache::get_thread_local_env()?)
434+
InvocationArg::new_2(arg, JavaClass::Long.into(), cache::get_thread_local_env()?)
444435
}
445436
}
446437

447438
impl<'a> TryFrom<&'a f32> for InvocationArg {
448439
type Error = errors::J4RsError;
449440
fn try_from(arg: &'a f32) -> errors::Result<InvocationArg> {
450-
InvocationArg::new_2(arg, CLASS_FLOAT, cache::get_thread_local_env()?)
441+
InvocationArg::new_2(arg, JavaClass::Float.into(), cache::get_thread_local_env()?)
451442
}
452443
}
453444

454445
impl<'a> TryFrom<&'a f64> for InvocationArg {
455446
type Error = errors::J4RsError;
456447
fn try_from(arg: &'a f64) -> errors::Result<InvocationArg> {
457-
InvocationArg::new_2(arg, CLASS_DOUBLE, cache::get_thread_local_env()?)
448+
InvocationArg::new_2(arg, JavaClass::Double.into(), cache::get_thread_local_env()?)
449+
}
450+
}
451+
452+
impl<'a, T: 'static> TryFrom<(&'a [T], &'a str)> for InvocationArg where T: Serialize {
453+
type Error = errors::J4RsError;
454+
fn try_from(vec: (&'a [T], &'a str)) -> errors::Result<InvocationArg> {
455+
let (vec, elements_class_name) = vec;
456+
let jni_env = cache::get_thread_local_env()?;
457+
let args: errors::Result<Vec<InvocationArg>> = vec.iter()
458+
.map(|elem| InvocationArg::new_2(elem, JavaClass::Of(elements_class_name).into(), jni_env)).collect();
459+
let res = Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
460+
Ok(InvocationArg::from(res?))
458461
}
459462
}
460463

461464
#[cfg(test)]
462465
mod inv_arg_unit_tests {
463466
use serde::Deserialize;
467+
464468
use crate::JvmBuilder;
469+
465470
use super::*;
466471

467472
#[test]

rust/src/api/mod.rs

Lines changed: 94 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,16 @@ pub(crate) mod instance;
6565
// Initialize the environment
6666
include!(concat!(env!("OUT_DIR"), "/j4rs_init.rs"));
6767

68-
pub(crate) const CLASS_STRING: &'static str = "java.lang.String";
69-
pub(crate) const CLASS_BOOLEAN: &'static str = "java.lang.Boolean";
70-
pub(crate) const CLASS_BYTE: &'static str = "java.lang.Byte";
71-
pub(crate) const CLASS_CHARACTER: &'static str = "java.lang.Character";
72-
pub(crate) const CLASS_SHORT: &'static str = "java.lang.Short";
73-
pub(crate) const CLASS_INTEGER: &'static str = "java.lang.Integer";
74-
pub(crate) const CLASS_LONG: &'static str = "java.lang.Long";
75-
pub(crate) const CLASS_FLOAT: &'static str = "java.lang.Float";
76-
pub(crate) const CLASS_DOUBLE: &'static str = "java.lang.Double";
77-
pub(crate) const CLASS_LIST: &'static str = "java.util.List";
68+
const CLASS_STRING: &'static str = "java.lang.String";
69+
const CLASS_BOOLEAN: &'static str = "java.lang.Boolean";
70+
const CLASS_BYTE: &'static str = "java.lang.Byte";
71+
const CLASS_CHARACTER: &'static str = "java.lang.Character";
72+
const CLASS_SHORT: &'static str = "java.lang.Short";
73+
const CLASS_INTEGER: &'static str = "java.lang.Integer";
74+
const CLASS_LONG: &'static str = "java.lang.Long";
75+
const CLASS_FLOAT: &'static str = "java.lang.Float";
76+
const CLASS_DOUBLE: &'static str = "java.lang.Double";
77+
const CLASS_LIST: &'static str = "java.util.List";
7878
pub(crate) const CLASS_NATIVE_CALLBACK_TO_RUST_CHANNEL_SUPPORT: &'static str = "org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport";
7979
pub(crate) const CLASS_J4RS_EVENT_HANDLER: &'static str = "org.astonbitecode.j4rs.api.jfx.handlers.J4rsEventHandler";
8080
pub(crate) const CLASS_J4RS_FXML_LOADER: &'static str = "org.astonbitecode.j4rs.api.jfx.J4rsFxmlLoader";
@@ -424,10 +424,18 @@ impl Jvm {
424424
/// Creates a new Java List with elements of the class `class_name`.
425425
/// The array will have the `InvocationArg`s populated.
426426
/// The `InvocationArg`s __must__ be of type _class_name_.
427+
#[deprecated(since="0.15.0", note="Please use `java_list` instead")]
427428
pub fn create_java_list(&self, class_name: &str, inv_args: &[InvocationArg]) -> errors::Result<Instance> {
428429
Jvm::do_create_java_list(self.jni_env, class_name, inv_args)
429430
}
430431

432+
/// Creates a new Java List with elements of the class `inner_class_name`.
433+
/// The array will have the `InvocationArg`s populated.
434+
pub fn java_list<'a>(&self, inner_class_name: impl Into<&'a str>, inv_args: Vec<impl TryInto<InvocationArg, Error=J4RsError>>) -> errors::Result<Instance> {
435+
let v: Result<Vec<InvocationArg>, J4RsError> = inv_args.into_iter().map(|arg| arg.try_into()).collect();
436+
Self::do_create_java_list(self.jni_env, inner_class_name.into(), v?.as_ref())
437+
}
438+
431439
fn do_create_java_list(jni_env: *mut JNIEnv, class_name: &str, inv_args: &[InvocationArg]) -> errors::Result<Instance> {
432440
debug(&format!("Creating a java list of class {} with {} elements", class_name, inv_args.len()));
433441
unsafe {
@@ -1352,6 +1360,66 @@ impl<'a> JvmBuilder<'a> {
13521360
}
13531361
}
13541362

1363+
/// Represents default, known Classes in Java. Can be used as class argument in `Jvm#java_list`, etc.
1364+
pub enum JavaClass<'a> {
1365+
Void,
1366+
String,
1367+
Boolean,
1368+
Byte,
1369+
Character,
1370+
Short,
1371+
Integer,
1372+
Long,
1373+
Float,
1374+
Double,
1375+
List,
1376+
Of(&'a str),
1377+
}
1378+
1379+
impl<'a> JavaClass<'a> {
1380+
pub fn get_class_str(&self) -> &'a str {
1381+
match self {
1382+
Self::Void => "void",
1383+
Self::String => CLASS_STRING,
1384+
Self::Boolean => CLASS_BOOLEAN,
1385+
Self::Byte => CLASS_BYTE,
1386+
Self::Character => CLASS_CHARACTER,
1387+
Self::Short => CLASS_SHORT,
1388+
Self::Integer => CLASS_INTEGER,
1389+
Self::Long => CLASS_LONG,
1390+
Self::Float => CLASS_FLOAT,
1391+
Self::Double => CLASS_DOUBLE,
1392+
Self::List => CLASS_LIST,
1393+
Self::Of(str) => str,
1394+
}
1395+
}
1396+
}
1397+
1398+
impl<'a> From<JavaClass<'a>> for &'a str {
1399+
fn from(java_class: JavaClass<'a>) -> &'a str {
1400+
java_class.get_class_str()
1401+
}
1402+
}
1403+
1404+
impl <'a> From<&'a str> for JavaClass<'a> {
1405+
fn from(java_class: &'a str) -> JavaClass<'a> {
1406+
match java_class {
1407+
"void" => Self::Void,
1408+
CLASS_STRING => Self::String,
1409+
CLASS_BOOLEAN => Self::Boolean,
1410+
CLASS_BYTE => Self::Byte,
1411+
CLASS_CHARACTER => Self::Character,
1412+
CLASS_SHORT => Self::Short,
1413+
CLASS_INTEGER => Self::Integer,
1414+
CLASS_LONG => Self::Long,
1415+
CLASS_FLOAT => Self::Float,
1416+
CLASS_DOUBLE => Self::Double,
1417+
CLASS_LIST => Self::List,
1418+
str => Self::Of(str),
1419+
}
1420+
}
1421+
}
1422+
13551423
/// Represents Java's null. Use this to create null Objects. E.g.:
13561424
///
13571425
/// let null_integer = InvocationArg::from(Null::Integer);
@@ -1471,4 +1539,20 @@ mod api_unit_tests {
14711539
assert!(index1 == 0);
14721540
assert!(index2 == 1);
14731541
}
1542+
1543+
#[test]
1544+
fn test_java_class_creation() {
1545+
assert_eq!(JavaClass::Void.get_class_str(), "void");
1546+
assert_eq!(JavaClass::String.get_class_str(), CLASS_STRING);
1547+
assert_eq!(JavaClass::Boolean.get_class_str(), CLASS_BOOLEAN);
1548+
assert_eq!(JavaClass::Byte.get_class_str(), CLASS_BYTE);
1549+
assert_eq!(JavaClass::Character.get_class_str(), CLASS_CHARACTER);
1550+
assert_eq!(JavaClass::Short.get_class_str(), CLASS_SHORT);
1551+
assert_eq!(JavaClass::Integer.get_class_str(), CLASS_INTEGER);
1552+
assert_eq!(JavaClass::Long.get_class_str(), CLASS_LONG);
1553+
assert_eq!(JavaClass::Float.get_class_str(), CLASS_FLOAT);
1554+
assert_eq!(JavaClass::Double.get_class_str(), CLASS_DOUBLE);
1555+
assert_eq!(JavaClass::List.get_class_str(), CLASS_LIST);
1556+
assert_eq!(JavaClass::Of("a.java.Class").get_class_str(), "a.java.Class");
1557+
}
14741558
}

0 commit comments

Comments
 (0)