Skip to content

Commit

Permalink
#41: Fix failing to_rust basic types generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
astonbitecode committed Dec 7, 2022
1 parent 4f44f81 commit bacfc25
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 37 deletions.
106 changes: 97 additions & 9 deletions rust/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ const CLASS_LONG: &'static str = "java.lang.Long";
const CLASS_FLOAT: &'static str = "java.lang.Float";
const CLASS_DOUBLE: &'static str = "java.lang.Double";
const CLASS_LIST: &'static str = "java.util.List";
pub(crate) const PRIMITIVE_BOOLEAN: &'static str = "boolean";
pub(crate) const PRIMITIVE_BYTE: &'static str = "byte";
pub(crate) const PRIMITIVE_SHORT: &'static str = "short";
pub(crate) const PRIMITIVE_INT: &'static str = "int";
pub(crate) const PRIMITIVE_LONG: &'static str = "long";
pub(crate) const PRIMITIVE_FLOAT: &'static str = "float";
pub(crate) const PRIMITIVE_DOUBLE: &'static str = "double";
pub(crate) const PRIMITIVE_CHAR: &'static str = "char";
pub(crate) const CLASS_NATIVE_CALLBACK_TO_RUST_CHANNEL_SUPPORT: &'static str = "org.astonbitecode.j4rs.api.invocation.NativeCallbackToRustChannelSupport";
pub(crate) const CLASS_J4RS_EVENT_HANDLER: &'static str = "org.astonbitecode.j4rs.api.jfx.handlers.J4rsEventHandler";
pub(crate) const CLASS_J4RS_FXML_LOADER: &'static str = "org.astonbitecode.j4rs.api.jfx.J4rsFxmlLoader";
Expand Down Expand Up @@ -219,6 +227,10 @@ impl Jvm {
let _ = cache::get_jni_get_string_utf_chars().or_else(|| cache::set_jni_get_string_utf_chars((**jni_environment).GetStringUTFChars));
let _ = cache::get_jni_release_string_utf_chars().or_else(|| cache::set_jni_release_string_utf_chars((**jni_environment).ReleaseStringUTFChars));
let _ = cache::get_jni_call_object_method().or_else(|| cache::set_jni_call_object_method((**jni_environment).CallObjectMethod));
let _ = cache::get_jni_call_byte_method().or_else(|| cache::set_jni_call_byte_method((**jni_environment).CallByteMethod));
let _ = cache::get_jni_call_short_method().or_else(|| cache::set_jni_call_short_method((**jni_environment).CallShortMethod));
let _ = cache::get_jni_call_int_method().or_else(|| cache::set_jni_call_int_method((**jni_environment).CallIntMethod));
let _ = cache::get_jni_call_long_method().or_else(|| cache::set_jni_call_long_method((**jni_environment).CallLongMethod));
let _ = cache::get_jni_call_float_method().or_else(|| cache::set_jni_call_float_method((**jni_environment).CallFloatMethod));
let _ = cache::get_jni_call_double_method().or_else(|| cache::set_jni_call_double_method((**jni_environment).CallDoubleMethod));
let _ = cache::get_jni_call_void_method().or_else(|| cache::set_jni_call_void_method((**jni_environment).CallVoidMethod));
Expand Down Expand Up @@ -937,19 +949,19 @@ impl Jvm {
let object_class_name_instance = jni_utils::create_global_ref_from_local_ref(object_class_name_instance, self.jni_env)?;
let ref class_name = jni_utils::string_from_jobject(object_class_name_instance, self.jni_env)?;
jni_utils::delete_java_ref(self.jni_env, object_class_name_instance);
if t_type == TypeId::of::<String>() && CLASS_STRING == class_name {
if t_type == TypeId::of::<String>() && JavaClass::String.get_class_str() == class_name {
rust_box_from_java_object!(jni_utils::string_from_jobject)
} else if t_type == TypeId::of::<i32>() && CLASS_INTEGER == class_name {
} else if t_type == TypeId::of::<i32>() && (JavaClass::Integer.get_class_str() == class_name || PRIMITIVE_INT == class_name) {
rust_box_from_java_object!(jni_utils::i32_from_jobject)
} else if t_type == TypeId::of::<i8>() && CLASS_BYTE == class_name {
} else if t_type == TypeId::of::<i8>() && (JavaClass::Byte.get_class_str() == class_name || PRIMITIVE_BYTE == class_name) {
rust_box_from_java_object!(jni_utils::i8_from_jobject)
} else if t_type == TypeId::of::<i16>() && CLASS_SHORT == class_name {
} else if t_type == TypeId::of::<i16>() && (JavaClass::Short.get_class_str() == class_name || PRIMITIVE_SHORT == class_name) {
rust_box_from_java_object!(jni_utils::i16_from_jobject)
} else if t_type == TypeId::of::<i64>() && CLASS_LONG == class_name {
} else if t_type == TypeId::of::<i64>() && (JavaClass::Long.get_class_str() == class_name || PRIMITIVE_LONG == class_name) {
rust_box_from_java_object!(jni_utils::i64_from_jobject)
} else if t_type == TypeId::of::<f32>() && CLASS_FLOAT == class_name {
} else if t_type == TypeId::of::<f32>() && (JavaClass::Float.get_class_str() == class_name || PRIMITIVE_FLOAT == class_name) {
rust_box_from_java_object!(jni_utils::f32_from_jobject)
} else if t_type == TypeId::of::<f64>() && CLASS_DOUBLE == class_name {
} else if t_type == TypeId::of::<f64>() && (JavaClass::Double.get_class_str() == class_name || PRIMITIVE_DOUBLE == class_name) {
rust_box_from_java_object!(jni_utils::f64_from_jobject)
} else {
Ok(Box::new(self.to_rust_deserialized(instance)?))
Expand Down Expand Up @@ -1626,8 +1638,6 @@ mod api_unit_tests {
let (index1, _) = Jvm::select_timeout(&[&ir1, &ir2], &d).unwrap();
let (index2, _) = Jvm::select_timeout(&[&ir1, &ir2], &d).unwrap();
assert!(Jvm::select_timeout(&[&ir1, &ir2], &d).is_err());
dbg!(index1);
dbg!(index2);
assert!(index1 == 0);
assert!(index2 == 1);
}
Expand All @@ -1647,4 +1657,82 @@ mod api_unit_tests {
assert_eq!(JavaClass::List.get_class_str(), CLASS_LIST);
assert_eq!(JavaClass::Of("a.java.Class").get_class_str(), "a.java.Class");
}

#[test]
fn test_int_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: i32 = 3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_INTEGER, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "intValue", &[]).unwrap();
let rust_value_from_java: i32 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: i32 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}

#[test]
fn test_byte_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: i8 = 3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_BYTE, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "byteValue", &[]).unwrap();
let rust_value_from_java: i8 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: i8 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}

#[test]
fn test_short_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: i16 = 3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_SHORT, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "shortValue", &[]).unwrap();
let rust_value_from_java: i16 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: i16 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}

#[test]
fn test_long_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: i64 = 3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_LONG, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "longValue", &[]).unwrap();
let rust_value_from_java: i64 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: i64 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}

#[test]
fn test_float_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: f32 = 3.3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_FLOAT, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "floatValue", &[]).unwrap();
let rust_value_from_java: f32 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: f32 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}

#[test]
fn test_double_to_rust() {
let jvm = JvmBuilder::new().build().unwrap();
let rust_value: f64 = 3.3;
let ia = InvocationArg::try_from(rust_value).unwrap().into_primitive().unwrap();
let java_instance = jvm.create_instance(CLASS_DOUBLE, &[ia]).unwrap();
let java_primitive_instance = jvm.invoke(&java_instance, "doubleValue", &[]).unwrap();
let rust_value_from_java: f64 = jvm.to_rust(java_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
let rust_value_from_java: f64 = jvm.to_rust(java_primitive_instance).unwrap();
assert_eq!(rust_value_from_java, rust_value);
}
}
83 changes: 68 additions & 15 deletions rust/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,7 @@ use std::cell::RefCell;
use std::path::PathBuf;
use std::sync::Mutex;

use jni_sys::{
self,
jboolean,
jclass,
jdouble,
jfloat,
jint,
jmethodID,
JNIEnv,
jobject,
jobjectArray,
jsize,
jstring,
};
use jni_sys::{self, jboolean, jbyte, jclass, jdouble, jfloat, jint, jlong, jmethodID, JNIEnv, jobject, jobjectArray, jshort, jsize, jstring};
use libc::c_char;

use crate::{api_tweaks as tweaks, errors, jni_utils, utils};
Expand All @@ -54,6 +41,14 @@ pub(crate) type JniReleaseStringUTFChars = unsafe extern "system" fn(env: *mut J
#[allow(non_snake_case)]
pub(crate) type JniCallObjectMethod = unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jobject;
#[allow(non_snake_case)]
pub(crate) type JniCallIntMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jint;
#[allow(non_snake_case)]
pub(crate) type JniCallByteMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jbyte;
#[allow(non_snake_case)]
pub(crate) type JniCallShortMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jshort;
#[allow(non_snake_case)]
pub(crate) type JniCallLongMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jlong;
#[allow(non_snake_case)]
pub(crate) type JniCallFloatMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jfloat;
#[allow(non_snake_case)]
pub(crate) type JniCallDoubleMethod = unsafe extern "C" fn(_: *mut JNIEnv, _: jobject, _: jmethodID, ...) -> jdouble;
Expand Down Expand Up @@ -90,6 +85,10 @@ thread_local! {
pub(crate) static JNI_GET_STRING_UTF_CHARS: RefCell<Option<JniGetStringUTFChars>> = RefCell::new(None);
pub(crate) static JNI_RELEASE_STRING_UTF_CHARS: RefCell<Option<JniReleaseStringUTFChars>> = RefCell::new(None);
pub(crate) static JNI_CALL_OBJECT_METHOD: RefCell<Option<JniCallObjectMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_INT_METHOD: RefCell<Option<JniCallIntMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_BYTE_METHOD: RefCell<Option<JniCallByteMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_SHORT_METHOD: RefCell<Option<JniCallShortMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_LONG_METHOD: RefCell<Option<JniCallLongMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_FLOAT_METHOD: RefCell<Option<JniCallFloatMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_DOUBLE_METHOD: RefCell<Option<JniCallDoubleMethod>> = RefCell::new(None);
pub(crate) static JNI_CALL_VOID_METHOD: RefCell<Option<JniCallVoidMethod>> = RefCell::new(None);
Expand Down Expand Up @@ -347,6 +346,61 @@ pub(crate) fn set_jni_call_void_method(j: Option<JniCallVoidMethod>) -> Option<J
get_jni_call_void_method()
}

pub(crate) fn set_jni_call_byte_method(j: Option<JniCallByteMethod>) -> Option<JniCallByteMethod> {
debug("Called set_jni_call_byte_method");
JNI_CALL_BYTE_METHOD.with(|opt| {
*opt.borrow_mut() = j;
});
get_jni_call_byte_method()
}

pub(crate) fn get_jni_call_byte_method() -> Option<JniCallByteMethod> {
JNI_CALL_BYTE_METHOD.with(|opt| {
*opt.borrow()
})
}

pub(crate) fn set_jni_call_short_method(j: Option<JniCallShortMethod>) -> Option<JniCallShortMethod> {
debug("Called set_jni_call_short_method");
JNI_CALL_SHORT_METHOD.with(|opt| {
*opt.borrow_mut() = j;
});
get_jni_call_short_method()
}

pub(crate) fn get_jni_call_short_method() -> Option<JniCallShortMethod> {
JNI_CALL_SHORT_METHOD.with(|opt| {
*opt.borrow()
})
}

pub(crate) fn set_jni_call_int_method(j: Option<JniCallIntMethod>) -> Option<JniCallIntMethod> {
debug("Called set_jni_call_int_method");
JNI_CALL_INT_METHOD.with(|opt| {
*opt.borrow_mut() = j;
});
get_jni_call_int_method()
}

pub(crate) fn get_jni_call_int_method() -> Option<JniCallIntMethod> {
JNI_CALL_INT_METHOD.with(|opt| {
*opt.borrow()
})
}

pub(crate) fn set_jni_call_long_method(j: Option<JniCallLongMethod>) -> Option<JniCallLongMethod> {
debug("Called set_jni_call_long_method");
JNI_CALL_LONG_METHOD.with(|opt| {
*opt.borrow_mut() = j;
});
get_jni_call_long_method()
}

pub(crate) fn get_jni_call_long_method() -> Option<JniCallLongMethod> {
JNI_CALL_LONG_METHOD.with(|opt| {
*opt.borrow()
})
}

pub(crate) fn set_jni_call_float_method(j: Option<JniCallFloatMethod>) -> Option<JniCallFloatMethod> {
debug("Called set_jni_call_float_method");
Expand All @@ -362,7 +416,6 @@ pub(crate) fn get_jni_call_float_method() -> Option<JniCallFloatMethod> {
})
}


pub(crate) fn set_jni_call_double_method(j: Option<JniCallDoubleMethod>) -> Option<JniCallDoubleMethod> {
debug("Called set_jni_call_double_method");
JNI_CALL_DOUBLE_METHOD.with(|opt| {
Expand Down
8 changes: 4 additions & 4 deletions rust/src/jni_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ pub(crate) unsafe fn i8_from_jobject(obj: jobject, jni_env: *mut JNIEnv) -> erro
if obj.is_null() {
Err(errors::J4RsError::JniError("Attempt to create an i8 from null".to_string()))
} else {
let v = (opt_to_res(cache::get_jni_call_object_method())?)(
let v = (opt_to_res(cache::get_jni_call_byte_method())?)(
jni_env,
obj,
cache::get_byte_to_byte_method()?,
Expand All @@ -302,7 +302,7 @@ pub(crate) unsafe fn i16_from_jobject(obj: jobject, jni_env: *mut JNIEnv) -> err
if obj.is_null() {
Err(errors::J4RsError::JniError("Attempt to create an i16 from null".to_string()))
} else {
let v = (opt_to_res(cache::get_jni_call_object_method())?)(
let v = (opt_to_res(cache::get_jni_call_short_method())?)(
jni_env,
obj,
cache::get_short_to_short_method()?,
Expand All @@ -328,7 +328,7 @@ pub(crate) unsafe fn i32_from_jobject(obj: jobject, jni_env: *mut JNIEnv) -> err
if obj.is_null() {
Err(errors::J4RsError::JniError("Attempt to create an i32 from null".to_string()))
} else {
let v = (opt_to_res(cache::get_jni_call_object_method())?)(
let v = (opt_to_res(cache::get_jni_call_int_method())?)(
jni_env,
obj,
cache::get_integer_to_int_method()?,
Expand All @@ -354,7 +354,7 @@ pub(crate) unsafe fn i64_from_jobject(obj: jobject, jni_env: *mut JNIEnv) -> err
if obj.is_null() {
Err(errors::J4RsError::JniError("Attempt to create an i64 from null".to_string()))
} else {
let v = (opt_to_res(cache::get_jni_call_object_method())?)(
let v = (opt_to_res(cache::get_jni_call_long_method())?)(
jni_env,
obj,
cache::get_long_to_long_method()?,
Expand Down
19 changes: 10 additions & 9 deletions rust/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use fs_extra::dir::get_dir_content;
use libc::{self, c_char};

use crate::{cache, errors, InvocationArg, JavaClass};
use crate::api::{PRIMITIVE_BOOLEAN, PRIMITIVE_BYTE, PRIMITIVE_CHAR, PRIMITIVE_DOUBLE, PRIMITIVE_FLOAT, PRIMITIVE_INT, PRIMITIVE_LONG, PRIMITIVE_SHORT};

pub fn to_rust_string(pointer: *const c_char) -> String {
let slice = unsafe { CStr::from_ptr(pointer).to_bytes() };
Expand Down Expand Up @@ -86,7 +87,7 @@ pub(crate) fn default_jassets_path() -> errors::Result<PathBuf> {
let mut jassets_path = if is_build_script {
PathBuf::from(env::var("OUT_DIR")?)
} else {
std::env::current_exe()?
env::current_exe()?
};
let mut tmp_vec = Vec::new();

Expand Down Expand Up @@ -146,14 +147,14 @@ fn find_j4rs_dynamic_libraries_dir_entries() -> errors::Result<Vec<fs::DirEntry>

pub(crate) fn primitive_of(inv_arg: &InvocationArg) -> Option<String> {
match get_class_name(inv_arg).into() {
JavaClass::Boolean => Some("boolean".to_string()),
JavaClass::Byte => Some("byte".to_string()),
JavaClass::Short => Some("short".to_string()),
JavaClass::Integer => Some("int".to_string()),
JavaClass::Long => Some("long".to_string()),
JavaClass::Float => Some("float".to_string()),
JavaClass::Double => Some("double".to_string()),
JavaClass::Character => Some("char".to_string()),
JavaClass::Boolean => Some(PRIMITIVE_BOOLEAN.to_string()),
JavaClass::Byte => Some(PRIMITIVE_BYTE.to_string()),
JavaClass::Short => Some(PRIMITIVE_SHORT.to_string()),
JavaClass::Integer => Some(PRIMITIVE_INT.to_string()),
JavaClass::Long => Some(PRIMITIVE_LONG.to_string()),
JavaClass::Float => Some(PRIMITIVE_FLOAT.to_string()),
JavaClass::Double => Some(PRIMITIVE_DOUBLE.to_string()),
JavaClass::Character => Some(PRIMITIVE_CHAR.to_string()),
JavaClass::Void => Some("void".to_string()),
_ => None,
}
Expand Down

0 comments on commit bacfc25

Please sign in to comment.