1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
//! This library provides a procedural macro to make easier to write JNI-compatible code in Rust.
//!
//! It can perform automatic conversion of Rust-y input and output types (see the [limitations](#limitations)).
//!
//! ```toml
//! [dependencies]
//! robusta_jni = "0.0.3"
//! ```
//!
//! ## Usage
//! All that's needed is a couple of attributes in the right places.
//!
//! First, a `#[bridge]` attribute on a module will enable it to be processed by `robusta`.
//!
//! Then, we will need a struct for every class with a native method that will be implemented in Rust,
//! and each of these structs will have to be annotated with a `#[package]` attribute
//! with the name of the Java package the corresponding class belongs to.
//!
//! After that, the functions implemented can be written as ordinary Rust functions, and the macro will
//! take care of converting to and from Java types. By default if a conversion fails a Java exception is thrown.
//!
//! **NOTE: This library currently supports static methods only.**
//!
//! ## Example
//! ### Rust side
//! ```rust
//! use robusta_jni::bridge;
//!
//! #[bridge]
//! mod jni {
//!     #[package(com.example.robusta)]
//!     struct HelloWorld;
//!
//!     impl HelloWorld {
//!         fn special(mut input1: Vec<i32>, input2: i32) -> Vec<String> {
//!             input1.push(input2);
//!             input1.iter().map(ToString::to_string).collect()
//!         }
//!     }
//! }
//! ```
//!
//! ### Java side
//! ```java
//! package com.example.robusta;
//!
//! import java.util.*;
//!
//! class HelloWorld {
//!     private static native ArrayList<String> special(ArrayList<Integer> input1, int input2);
//!
//!     static {
//!         System.loadLibrary("robusta_example");
//!     }
//!
//!     public static void main(String[] args) {
//!         ArrayList<String> output = HelloWorld.special(new ArrayList<Integer>(List.of(1, 2, 3)), 4);
//!         System.out.println(output)
//!     }
//! }
//! ```
//!
//! ## Type conversion details and extension to custom types
//! There are four traits that control how Rust types are converted to/from Java types:
//! `(Try)FromJavaValue` and `(Try)IntoJavaValue`.
//!
//! These traits are used for input and output types respectively, and implementing them
//! is necessary to allow the library to perform automatic type conversion. By default, the `Try` variants are used,
//! all of which throw a Java exception upon failure. This behaviour can be changed via the `call_type` attribute
//! (see the `convert` module documentation for more details).
//!
//! These traits make use of type provided by the  [`jni`](https://crates.io/crates/jni) crate,
//! however to provide maximum compatibility with `robusta`, we suggest using the re-exported version under `robusta_jni::jni`.
//!
//! ### Conversion table
//!
//! | **Rust**                                                                           | **Java**                            |
//! |------------------------------------------------------------------------------------|-------------------------------------|
//! | [`i32`]                                                                            | `int`                               |
//! | [`bool`]                                                                           | `boolean`                           |
//! | [`char`]                                                                           | `char`                              |
//! | [`i8`]                                                                             | `byte`                              |
//! | [`f32`]                                                                            | `float`                             |
//! | [`f64`]                                                                            | `double`                            |
//! | [`i64`]                                                                            | `long`                              |
//! | [`i16`]                                                                            | `short`                             |
//! | [`Vec<T>`](std::vec::Vec)†                                                         | `ArrayList<T>`                      |
//! | [`JObject<'env>`](jni::objects::JObject)‡                                          | *(any Java object as input type)*   |
//! | [`jobject`](jni::sys::jobject)                                                     | *(any Java object as output)*       |
//!
//! † Type parameter `T` must implement proper conversion types
//!
//! ‡ The special `'env` lifetime **must** be used
//!
//! ## Limitations
//! Only static methods are supported.
//!
//! Currently there are some limitations in the conversion mechanism:
//!  * Boxed types are supported only through the opaque `JObject`/`jobject` types
//!  * Automatic type conversion is limited to the table outlined above, though easily extendable if needed.
//!

pub use robusta_codegen::bridge;

pub mod convert;

#[cfg(not(feature = "no_jni"))]
pub use jni;