Skip to content

Optimize casting and fix local class reference leaks; refactor Env API; add Monitor, add docs, add is_same_object, fix ReferenceType generation #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed
3 changes: 3 additions & 0 deletions .github/workflows/rust_nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ jobs:
- uses: actions/checkout@v4
- run: rustup update nightly && rustup default nightly
- run: rustup component add rustfmt
- run: rustup component add clippy
- name: Check fmt
run: cargo fmt -- --check
- name: Clippy
run: cargo clippy -- -Dwarnings
- name: Test
run: cargo test
24 changes: 10 additions & 14 deletions java-spaghetti-gen/src/emit_rust/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,7 @@ impl<'a> Field<'a> {
writeln!(
out,
"{indent} \
let __jni_field = __FIELD.get_or_init(|| \
::java_spaghetti::JFieldID::from_raw(__jni_env.require_{}field(__jni_class, {}, {}))\
).as_raw();",
let __jni_field = *__FIELD.get_or_init(|| __jni_env.require_{}field(__jni_class, {}, {}));",
if self.java.is_static() { "static_" } else { "" },
StrEmitter(self.java.name()),
StrEmitter(FieldSigWriter(self.java.descriptor()))
Expand All @@ -188,7 +186,7 @@ impl<'a> Field<'a> {
} else {
writeln!(
out,
"{indent} __jni_env.get_{field_fragment}_field(self.as_raw(), __jni_field)",
"{indent} __jni_env.get_{field_fragment}_field(self, __jni_field)",
)?;
}
writeln!(out, "{indent} }}")?;
Expand Down Expand Up @@ -228,9 +226,7 @@ impl<'a> Field<'a> {
writeln!(
out,
"{indent} \
let __jni_field = __FIELD.get_or_init(|| \
::java_spaghetti::JFieldID::from_raw(__jni_env.require_{}field(__jni_class, {}, {}))\
).as_raw();",
let __jni_field = *__FIELD.get_or_init(|| __jni_env.require_{}field(__jni_class, {}, {}));",
if self.java.is_static() { "static_" } else { "" },
StrEmitter(self.java.name()),
StrEmitter(FieldSigWriter(self.java.descriptor()))
Expand All @@ -245,7 +241,7 @@ impl<'a> Field<'a> {
writeln!(
out,
"{indent} \
__jni_env.set_{field_fragment}_field(self.as_raw(), __jni_field, value)",
__jni_env.set_{field_fragment}_field(self, __jni_field, value)",
)?;
}
writeln!(out, "{indent} }}")?;
Expand Down Expand Up @@ -283,17 +279,17 @@ impl std::fmt::Display for ConstantWriter<'_> {
LiteralConstant::Long(value) => write!(f, "{}i64", value),

LiteralConstant::Float(value) if value.is_infinite() && *value < 0.0 => {
write!(f, "::std::f32::NEG_INFINITY")
write!(f, "f32::NEG_INFINITY")
}
LiteralConstant::Float(value) if value.is_infinite() => write!(f, "::std::f32::INFINITY"),
LiteralConstant::Float(value) if value.is_nan() => write!(f, "::std::f32::NAN"),
LiteralConstant::Float(value) if value.is_infinite() => write!(f, "f32::INFINITY"),
LiteralConstant::Float(value) if value.is_nan() => write!(f, "f32::NAN"),
LiteralConstant::Float(value) => write!(f, "{}f32", value),

LiteralConstant::Double(value) if value.is_infinite() && *value < 0.0 => {
write!(f, "::std::f64::NEG_INFINITY")
write!(f, "f64::NEG_INFINITY")
}
LiteralConstant::Double(value) if value.is_infinite() => write!(f, "::std::f64::INFINITY"),
LiteralConstant::Double(value) if value.is_nan() => write!(f, "::std::f64::NAN"),
LiteralConstant::Double(value) if value.is_infinite() => write!(f, "f64::INFINITY"),
LiteralConstant::Double(value) if value.is_nan() => write!(f, "f64::NAN"),
LiteralConstant::Double(value) => write!(f, "{}f64", value),

LiteralConstant::String(value) => std::fmt::Debug::fmt(value, f),
Expand Down
10 changes: 4 additions & 6 deletions java-spaghetti-gen/src/emit_rust/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,7 @@ impl<'a> Method<'a> {
writeln!(
out,
"{indent} \
let __jni_method = __METHOD.get_or_init(|| \
::java_spaghetti::JMethodID::from_raw(__jni_env.require_{}method(__jni_class, {}, {}))\
).as_raw();",
let __jni_method = *__METHOD.get_or_init(|| __jni_env.require_{}method(__jni_class, {}, {}));",
if self.java.is_static() { "static_" } else { "" },
StrEmitter(self.java.name()),
StrEmitter(MethodSigWriter(self.java.descriptor()))
Expand All @@ -236,20 +234,20 @@ impl<'a> Method<'a> {
writeln!(
out,
"{indent} \
__jni_env.new_object_a(__jni_class, __jni_method, __jni_args.as_ptr())",
__jni_env.new_object_a(__jni_class, __jni_method, &__jni_args)",
)?;
} else if self.java.is_static() {
writeln!(
out,
"{indent} \
__jni_env.call_static_{}_method_a(__jni_class, __jni_method, __jni_args.as_ptr())",
__jni_env.call_static_{}_method_a(__jni_class, __jni_method, &__jni_args)",
ret_method_fragment
)?;
} else {
writeln!(
out,
"{indent} \
__jni_env.call_{}_method_a(self.as_raw(), __jni_method, __jni_args.as_ptr())",
__jni_env.call_{}_method_a(self, __jni_method, &__jni_args)",
ret_method_fragment
)?;
}
Expand Down
28 changes: 12 additions & 16 deletions java-spaghetti-gen/src/emit_rust/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,17 @@ impl Struct {

let rust_name = &self.rust.struct_name;
writeln!(out, "{attributes}{visibility} enum {rust_name}{{}}")?;
if !self.java.is_static() {
writeln!(out, "unsafe impl ::java_spaghetti::ReferenceType for {rust_name} {{}}")?;
}

writeln!(
out,
"unsafe impl ::java_spaghetti::JniType for {rust_name} {{\
\n fn static_with_jni_type<R>(callback: impl FnOnce(&str) -> R) -> R {{\
\n callback({})\
\n }}\
\n}}",
"unsafe impl ::java_spaghetti::ReferenceType for {rust_name} {{\
\n fn jni_reference_type_name() -> ::std::borrow::Cow<'static, str> {{\
\n ::std::borrow::Cow::Borrowed({})\
\n }}\
\n fn jni_get_class(__jni_env: ::java_spaghetti::Env) -> &'static ::java_spaghetti::JClass {{\
\n Self::__class_global_ref(__jni_env)\
\n }}\
\n}}",
StrEmitter(self.java.path().as_str()),
)?;

Expand Down Expand Up @@ -156,15 +157,10 @@ impl Struct {
writeln!(
out,
"\
\nfn __class_global_ref(__jni_env: ::java_spaghetti::Env) -> ::java_spaghetti::sys::jobject {{\
\n static __CLASS: ::std::sync::OnceLock<::java_spaghetti::Global<{}>> = ::std::sync::OnceLock::new();\
\n __CLASS.get_or_init(|| unsafe {{\
\n ::java_spaghetti::Local::from_raw(__jni_env, __jni_env.require_class({})).as_global()\
\n }}).as_raw()\
\nfn __class_global_ref(__jni_env: ::java_spaghetti::Env) -> &'static ::java_spaghetti::JClass {{\
\n static _CLASS: ::std::sync::OnceLock<::java_spaghetti::JClass> = ::std::sync::OnceLock::new();\
\n _CLASS.get_or_init(|| unsafe {{ __jni_env.require_class({}) }})\
\n}}",
context
.java_to_rust_path(Id("java/lang/Object"), &self.rust.mod_)
.unwrap(),
StrEmitter(self.java.path().as_str()),
)?;

Expand Down
1 change: 1 addition & 0 deletions java-spaghetti-gen/src/run/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Core generation logic

#[allow(clippy::module_inception)]
mod run;

pub use run::run;
Loading