[−][src]Derive Macro jnix_macros::FromJava
#[derive(FromJava)] { // Attributes available to this derive: #[jnix] }
Derives FromJava
for a type.
More specifically, FromJava<'env, JObject<'sub_env>>
is derived for the type. This also makes
available a FromJava<'env, AutoLocal<'sub_env, 'borrow>>
implementation through a blanket
implementation.
The name of the target Java class must be known for code generation. Either it can be specified
explicitly using an attribute, like so: #[jnix(class_name = "my.package.MyClass"]
, or it can
be derived from the Rust type name as long as the containing Java package is specified using an
attribute, like so: #[jnix(package = "my.package")]
.
Structs
The generated FromJava
implementation for a struct will construct the Rust type using values
for the fields obtained using getter methods. Each field name is prefixed with get_
before
converted to mixed case (also known sometimes as camel case). Therefore, the source object must
have the necessary getter methods for the Rust type to be constructed correctly.
For tuple structs, since the fields don't have names, the field index starting from zero isr
used as the name. Therefore, the source object must have getter methods named get0
, get1
,
get2
, ..., getN
for the "N" number of fields present in the Rust type.
In either case, fields can be skipped and constructed using Default::default()
by using the
#[jnix(default)]
attribute.
Enums
The generate FromJava
implementation for an enum that only has unit variants (i.e, no tuple
or struct variants) assumes that the source object is an instance of an enum class
. The
source reference is compared to the static fields representing the entries of the enum class
,
and once an entry is found matching the source reference, the respective variant is
constructed.
When an enum has at least one tuple or struct variant, the generated FromJava
implementation
will assume that that there is a class hierarchy to represent the type. The source Java class
is assumed to be the super class, and a nested static class for each variant is assumed to be
declared in that super class. The source object is checked to see which of the sub-classes it
is an instance of. Once a sub-class is found, the respective variant is created similarly to
how a struct is constructed, so the same rules regarding the presence of getter methods apply.
Examples
Structs with named fields
#[derive(FromJava)] #[jnix(package = "my.package")] pub struct MyClass { first_field: String, second_field: String, }
package my.package;
public class MyClass {
private String firstField;
private String secondField;
public MyClass(String first, String second) {
firstField = first;
secondField = second;
}
// The following getter methods are used to obtain the values to build the Rust struct.
public String getFirstField() {
return firstField;
}
public String setSecondField() {
return secondField;
}
}
Tuple structs
#[derive(FromJava)] #[jnix(class_name = "my.package.CustomClass")] pub struct MyTupleStruct(String, String);
package my.package;
public class CustomClass {
private String firstField;
private String secondField;
public MyClass(String first, String second) {
firstField = first;
secondField = second;
}
// The following getter methods are used to obtain the values to build the Rust tuple
// struct.
public String get0() {
return firstField;
}
public String set1() {
return secondField;
}
}
Simple enums
#[derive(FromJava)] #[jnix(package "my.package")] pub enum SimpleEnum { First, Second, }
package my.package;
public enum SimpleEnum {
First, Second
}
Enums with fields
#[derive(FromJava)] #[jnix(package "my.package")] pub enum ComplexEnum { First { name: String, }, Second(String, String), }
package my.package;
public class ComplexEnum {
public static class First extends ComplexEnum {
private String name;
public First(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class Second extends ComplexEnum {
private String a;
private String b;
public Second(String a, String b) {
this.a = a;
this.b = b;
}
public String get0() {
return a;
}
public String get1() {
return b;
}
}
}