Skip to content

Commit 612a762

Browse files
Merge pull request #97 from pickleburger/primitive_array
support primitive arrays in to_rust
2 parents d287785 + a9c05cc commit 612a762

File tree

4 files changed

+575
-4
lines changed

4 files changed

+575
-4
lines changed

rust/src/api/invocation_arg.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,15 @@ impl InvocationArg {
105105
class_name: class_name.to_string(),
106106
serialized: false,
107107
})
108+
} else if let Some(a) = arg_any.downcast_ref::<u16>() {
109+
Ok(InvocationArg::RustBasic {
110+
instance: Instance::new(
111+
jni_utils::global_jobject_from_u16(a, jni_env)?,
112+
class_name,
113+
)?,
114+
class_name: class_name.to_string(),
115+
serialized: false,
116+
})
108117
} else if let Some(a) = arg_any.downcast_ref::<i32>() {
109118
Ok(InvocationArg::RustBasic {
110119
instance: Instance::new(
@@ -446,6 +455,30 @@ impl<'a> TryFrom<&'a [i16]> for InvocationArg {
446455
}
447456
}
448457

458+
impl TryFrom<u16> for InvocationArg {
459+
type Error = errors::J4RsError;
460+
fn try_from(arg: u16) -> errors::Result<InvocationArg> {
461+
InvocationArg::new_2(
462+
&arg,
463+
JavaClass::Character.into(),
464+
cache::get_thread_local_env()?,
465+
)
466+
}
467+
}
468+
469+
impl<'a> TryFrom<&'a [u16]> for InvocationArg {
470+
type Error = errors::J4RsError;
471+
fn try_from(vec: &'a [u16]) -> errors::Result<InvocationArg> {
472+
let args: errors::Result<Vec<InvocationArg>> = vec
473+
.iter()
474+
.map(|elem| InvocationArg::try_from(elem))
475+
.collect();
476+
let res =
477+
Jvm::do_create_java_list(cache::get_thread_local_env()?, cache::J4RS_ARRAY, &args?);
478+
Ok(InvocationArg::from(res?))
479+
}
480+
}
481+
449482
impl TryFrom<i32> for InvocationArg {
450483
type Error = errors::J4RsError;
451484
fn try_from(arg: i32) -> errors::Result<InvocationArg> {
@@ -592,6 +625,13 @@ impl<'a> TryFrom<&'a i16> for InvocationArg {
592625
}
593626
}
594627

628+
impl<'a> TryFrom<&'a u16> for InvocationArg {
629+
type Error = errors::J4RsError;
630+
fn try_from(arg: &'a u16) -> errors::Result<InvocationArg> {
631+
InvocationArg::new_2(arg, JavaClass::Character.into(), cache::get_thread_local_env()?)
632+
}
633+
}
634+
595635
impl<'a, 'b> TryFrom<&'a i32> for InvocationArg {
596636
type Error = errors::J4RsError;
597637
fn try_from(arg: &'a i32) -> errors::Result<InvocationArg> {

rust/src/api/mod.rs

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ pub(crate) const PRIMITIVE_LONG: &'static str = "long";
7070
pub(crate) const PRIMITIVE_FLOAT: &'static str = "float";
7171
pub(crate) const PRIMITIVE_DOUBLE: &'static str = "double";
7272
pub(crate) const PRIMITIVE_CHAR: &'static str = "char";
73+
74+
pub(crate) const PRIMITIVE_BOOLEAN_ARRAY: &'static str = "[Z";
75+
pub(crate) const PRIMITIVE_BYTE_ARRAY: &'static str = "[B";
76+
pub(crate) const PRIMITIVE_SHORT_ARRAY: &'static str = "[S";
77+
pub(crate) const PRIMITIVE_INT_ARRAY: &'static str = "[I";
78+
pub(crate) const PRIMITIVE_LONG_ARRAY: &'static str = "[J";
79+
pub(crate) const PRIMITIVE_FLOAT_ARRAY: &'static str = "[F";
80+
pub(crate) const PRIMITIVE_DOUBLE_ARRAY: &'static str = "[D";
81+
pub(crate) const PRIMITIVE_CHAR_ARRAY: &'static str = "[C";
82+
7383
pub(crate) const CLASS_NATIVE_CALLBACK_TO_RUST_CHANNEL_SUPPORT: &'static str =
7484
"org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport";
7585
pub(crate) const CLASS_J4RS_EVENT_HANDLER: &'static str =
@@ -249,6 +259,9 @@ impl Jvm {
249259
let _ = cache::get_jni_call_short_method().or_else(|| {
250260
cache::set_jni_call_short_method(Some((**jni_environment).v1_6.CallShortMethod))
251261
});
262+
let _ = cache::get_jni_call_char_method().or_else(|| {
263+
cache::set_jni_call_char_method(Some((**jni_environment).v1_6.CallCharMethod))
264+
});
252265
let _ = cache::get_jni_call_int_method().or_else(|| {
253266
cache::set_jni_call_int_method(Some((**jni_environment).v1_6.CallIntMethod))
254267
});
@@ -269,6 +282,91 @@ impl Jvm {
269282
(**jni_environment).v1_6.CallStaticObjectMethod,
270283
))
271284
});
285+
let _ = cache::get_jni_get_array_length().or_else(|| {
286+
cache::set_jni_get_array_length(Some(
287+
(**jni_environment).v1_6.GetArrayLength,
288+
))
289+
});
290+
let _ = cache::get_jni_get_byte_array_elements().or_else(|| {
291+
cache::set_jni_get_byte_array_elements(Some(
292+
(**jni_environment).v1_6.GetByteArrayElements,
293+
))
294+
});
295+
let _ = cache::get_jni_release_byte_array_elements().or_else(|| {
296+
cache::set_jni_release_byte_array_elements(Some(
297+
(**jni_environment).v1_6.ReleaseByteArrayElements,
298+
))
299+
});
300+
let _ = cache::get_jni_get_short_array_elements().or_else(|| {
301+
cache::set_jni_get_short_array_elements(Some(
302+
(**jni_environment).v1_6.GetShortArrayElements,
303+
))
304+
});
305+
let _ = cache::get_jni_release_short_array_elements().or_else(|| {
306+
cache::set_jni_release_short_array_elements(Some(
307+
(**jni_environment).v1_6.ReleaseShortArrayElements,
308+
))
309+
});
310+
let _ = cache::get_jni_get_char_array_elements().or_else(|| {
311+
cache::set_jni_get_char_array_elements(Some(
312+
(**jni_environment).v1_6.GetCharArrayElements,
313+
))
314+
});
315+
let _ = cache::get_jni_release_char_array_elements().or_else(|| {
316+
cache::set_jni_release_char_array_elements(Some(
317+
(**jni_environment).v1_6.ReleaseCharArrayElements,
318+
))
319+
});
320+
let _ = cache::get_jni_get_int_array_elements().or_else(|| {
321+
cache::set_jni_get_int_array_elements(Some(
322+
(**jni_environment).v1_6.GetIntArrayElements,
323+
))
324+
});
325+
let _ = cache::get_jni_release_int_array_elements().or_else(|| {
326+
cache::set_jni_release_int_array_elements(Some(
327+
(**jni_environment).v1_6.ReleaseIntArrayElements,
328+
))
329+
});
330+
let _ = cache::get_jni_get_long_array_elements().or_else(|| {
331+
cache::set_jni_get_long_array_elements(Some(
332+
(**jni_environment).v1_6.GetLongArrayElements,
333+
))
334+
});
335+
let _ = cache::get_jni_release_long_array_elements().or_else(|| {
336+
cache::set_jni_release_long_array_elements(Some(
337+
(**jni_environment).v1_6.ReleaseLongArrayElements,
338+
))
339+
});
340+
let _ = cache::get_jni_get_float_array_elements().or_else(|| {
341+
cache::set_jni_get_float_array_elements(Some(
342+
(**jni_environment).v1_6.GetFloatArrayElements,
343+
))
344+
});
345+
let _ = cache::get_jni_release_float_array_elements().or_else(|| {
346+
cache::set_jni_release_float_array_elements(Some(
347+
(**jni_environment).v1_6.ReleaseFloatArrayElements,
348+
))
349+
});
350+
let _ = cache::get_jni_get_double_array_elements().or_else(|| {
351+
cache::set_jni_get_double_array_elements(Some(
352+
(**jni_environment).v1_6.GetDoubleArrayElements,
353+
))
354+
});
355+
let _ = cache::get_jni_release_double_array_elements().or_else(|| {
356+
cache::set_jni_release_double_array_elements(Some(
357+
(**jni_environment).v1_6.ReleaseDoubleArrayElements,
358+
))
359+
});
360+
let _ = cache::get_jni_get_boolean_array_elements().or_else(|| {
361+
cache::set_jni_get_boolean_array_elements(Some(
362+
(**jni_environment).v1_6.GetBooleanArrayElements,
363+
))
364+
});
365+
let _ = cache::get_jni_release_boolean_array_elements().or_else(|| {
366+
cache::set_jni_release_boolean_array_elements(Some(
367+
(**jni_environment).v1_6.ReleaseBooleanArrayElements,
368+
))
369+
});
272370
let _ = cache::get_jni_new_object_array().or_else(|| {
273371
cache::set_jni_new_object_array(Some((**jni_environment).v1_6.NewObjectArray))
274372
});
@@ -1167,6 +1265,10 @@ impl Jvm {
11671265
&& (JavaClass::Short.get_class_str() == class_name || PRIMITIVE_SHORT == class_name)
11681266
{
11691267
rust_box_from_java_object!(jni_utils::i16_from_jobject)
1268+
} else if t_type == TypeId::of::<u16>()
1269+
&& (JavaClass::Character.get_class_str() == class_name || PRIMITIVE_CHAR == class_name)
1270+
{
1271+
rust_box_from_java_object!(jni_utils::u16_from_jobject)
11701272
} else if t_type == TypeId::of::<i64>()
11711273
&& (JavaClass::Long.get_class_str() == class_name || PRIMITIVE_LONG == class_name)
11721274
{
@@ -1180,6 +1282,38 @@ impl Jvm {
11801282
|| PRIMITIVE_DOUBLE == class_name)
11811283
{
11821284
rust_box_from_java_object!(jni_utils::f64_from_jobject)
1285+
} else if t_type == TypeId::of::<Vec<i8>>()
1286+
&& PRIMITIVE_BYTE_ARRAY == class_name
1287+
{
1288+
rust_box_from_java_object!(jni_utils::i8_array_from_jobject)
1289+
} else if t_type == TypeId::of::<Vec<i16>>()
1290+
&& PRIMITIVE_SHORT_ARRAY == class_name
1291+
{
1292+
rust_box_from_java_object!(jni_utils::i16_array_from_jobject)
1293+
} else if t_type == TypeId::of::<Vec<u16>>()
1294+
&& PRIMITIVE_CHAR_ARRAY == class_name
1295+
{
1296+
rust_box_from_java_object!(jni_utils::u16_array_from_jobject)
1297+
} else if t_type == TypeId::of::<Vec<i32>>()
1298+
&& PRIMITIVE_INT_ARRAY == class_name
1299+
{
1300+
rust_box_from_java_object!(jni_utils::i32_array_from_jobject)
1301+
} else if t_type == TypeId::of::<Vec<i64>>()
1302+
&& PRIMITIVE_LONG_ARRAY == class_name
1303+
{
1304+
rust_box_from_java_object!(jni_utils::i64_array_from_jobject)
1305+
} else if t_type == TypeId::of::<Vec<f32>>()
1306+
&& PRIMITIVE_FLOAT_ARRAY == class_name
1307+
{
1308+
rust_box_from_java_object!(jni_utils::f32_array_from_jobject)
1309+
} else if t_type == TypeId::of::<Vec<f64>>()
1310+
&& PRIMITIVE_DOUBLE_ARRAY == class_name
1311+
{
1312+
rust_box_from_java_object!(jni_utils::f64_array_from_jobject)
1313+
} else if t_type == TypeId::of::<Vec<bool>>()
1314+
&& PRIMITIVE_BOOLEAN_ARRAY == class_name
1315+
{
1316+
rust_box_from_java_object!(jni_utils::boolean_array_from_jobject)
11831317
} else {
11841318
Ok(Box::new(self.to_rust_deserialized(instance)?))
11851319
}
@@ -1999,6 +2133,102 @@ mod api_unit_tests {
19992133
Ok(())
20002134
}
20012135

2136+
#[test]
2137+
fn test_byte_array_to_rust() -> errors::Result<()> {
2138+
let jvm = create_tests_jvm()?;
2139+
let rust_value: Vec<i8> = vec![-3_i8, 7_i8, 8_i8];
2140+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2141+
let java_instance = jvm.create_java_array(PRIMITIVE_BYTE, &ia)?;
2142+
let rust_value_from_java: Vec<i8> = jvm.to_rust(java_instance)?;
2143+
assert_eq!(rust_value_from_java, rust_value);
2144+
2145+
Ok(())
2146+
}
2147+
2148+
#[test]
2149+
fn test_short_array_to_rust() -> errors::Result<()> {
2150+
let jvm = create_tests_jvm()?;
2151+
let rust_value: Vec<i16> = vec![-3_i16, 7_i16, 10000_i16];
2152+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2153+
let java_instance = jvm.create_java_array(PRIMITIVE_SHORT, &ia)?;
2154+
let rust_value_from_java: Vec<i16> = jvm.to_rust(java_instance)?;
2155+
assert_eq!(rust_value_from_java, rust_value);
2156+
2157+
Ok(())
2158+
}
2159+
2160+
#[test]
2161+
fn test_char_array_to_rust() -> errors::Result<()> {
2162+
let jvm = create_tests_jvm()?;
2163+
let rust_value: Vec<u16> = vec![3_u16, 7_u16, 10000_u16];
2164+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2165+
let java_instance = jvm.create_java_array(PRIMITIVE_CHAR, &ia)?;
2166+
let rust_value_from_java: Vec<u16> = jvm.to_rust(java_instance)?;
2167+
assert_eq!(rust_value_from_java, rust_value);
2168+
2169+
Ok(())
2170+
}
2171+
2172+
#[test]
2173+
fn test_int_array_to_rust() -> errors::Result<()> {
2174+
let jvm = create_tests_jvm()?;
2175+
let rust_value: Vec<i32> = vec![-100_000, -1_000_000, 1_000_000];
2176+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2177+
let java_instance = jvm.create_java_array(PRIMITIVE_INT, &ia)?;
2178+
let rust_value_from_java: Vec<i32> = jvm.to_rust(java_instance)?;
2179+
assert_eq!(rust_value_from_java, rust_value);
2180+
2181+
Ok(())
2182+
}
2183+
2184+
#[test]
2185+
fn test_long_array_to_rust() -> errors::Result<()> {
2186+
let jvm = create_tests_jvm()?;
2187+
let rust_value: Vec<i64> = vec![-100_000, -1_000_000, 1_000_000];
2188+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2189+
let java_instance = jvm.create_java_array(PRIMITIVE_LONG, &ia)?;
2190+
let rust_value_from_java: Vec<i64> = jvm.to_rust(java_instance)?;
2191+
assert_eq!(rust_value_from_java, rust_value);
2192+
2193+
Ok(())
2194+
}
2195+
2196+
#[test]
2197+
fn test_float_array_to_rust() -> errors::Result<()> {
2198+
let jvm = create_tests_jvm()?;
2199+
let rust_value: Vec<f32> = vec![3_f32, 7.5_f32, -1000.5_f32];
2200+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2201+
let java_instance = jvm.create_java_array(PRIMITIVE_FLOAT, &ia)?;
2202+
let rust_value_from_java: Vec<f32> = jvm.to_rust(java_instance)?;
2203+
assert_eq!(rust_value_from_java, rust_value);
2204+
2205+
Ok(())
2206+
}
2207+
2208+
#[test]
2209+
fn test_double_array_to_rust() -> errors::Result<()> {
2210+
let jvm = create_tests_jvm()?;
2211+
let rust_value: Vec<f64> = vec![3_f64, 7.5_f64, -1000.5_f64];
2212+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2213+
let java_instance = jvm.create_java_array(PRIMITIVE_DOUBLE, &ia)?;
2214+
let rust_value_from_java: Vec<f64> = jvm.to_rust(java_instance)?;
2215+
assert_eq!(rust_value_from_java, rust_value);
2216+
2217+
Ok(())
2218+
}
2219+
2220+
#[test]
2221+
fn test_boolean_array_to_rust() -> errors::Result<()> {
2222+
let jvm = create_tests_jvm()?;
2223+
let rust_value: Vec<bool> = vec![false, true, false];
2224+
let ia: Vec<_> = rust_value.iter().map(|x| InvocationArg::try_from(x).unwrap().into_primitive().unwrap()).collect();
2225+
let java_instance = jvm.create_java_array(PRIMITIVE_BOOLEAN, &ia)?;
2226+
let rust_value_from_java: Vec<bool> = jvm.to_rust(java_instance)?;
2227+
assert_eq!(rust_value_from_java, rust_value);
2228+
2229+
Ok(())
2230+
}
2231+
20022232
#[test]
20032233
fn test_int_to_rust() -> errors::Result<()> {
20042234
let jvm = create_tests_jvm()?;
@@ -2044,6 +2274,21 @@ mod api_unit_tests {
20442274
Ok(())
20452275
}
20462276

2277+
#[test]
2278+
fn test_char_to_rust() -> errors::Result<()> {
2279+
let jvm = create_tests_jvm()?;
2280+
let rust_value: u16 = 3;
2281+
let ia = InvocationArg::try_from(rust_value)?.into_primitive()?;
2282+
let java_instance = jvm.create_instance(CLASS_CHARACTER, &[ia])?;
2283+
let java_primitive_instance = jvm.invoke(&java_instance, "charValue", InvocationArg::empty())?;
2284+
let rust_value_from_java: u16 = jvm.to_rust(java_instance)?;
2285+
assert_eq!(rust_value_from_java, rust_value);
2286+
let rust_value_from_java: u16 = jvm.to_rust(java_primitive_instance)?;
2287+
assert_eq!(rust_value_from_java, rust_value);
2288+
2289+
Ok(())
2290+
}
2291+
20472292
#[test]
20482293
fn test_long_to_rust() -> errors::Result<()> {
20492294
let jvm = create_tests_jvm()?;

0 commit comments

Comments
 (0)