// Copyright (c) 2017 rsjni developers
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.
//! Rust JNI Bindings for Java Interop.
//!
//! # Examples
//!
//! ## Java
//! We will be exercising the following Java class via Rust.
//!
//! ```java
//! //
//! // Test Class
//! //
//! import java.lang.System;
//! import java.util.Arrays;
//! import java.util.stream.Stream;
//! import java.util.stream.IntStream;
//!
//! public class Test {
//! public int current = 0;
//! public static String message = "Hello!";
//!
//! public Test(int current) {
//! this.current = current;
//! }
//!
//! public void incrementCurrent() {
//! this.current += 1;
//! }
//!
//! public int getCurrent() {
//! return this.current;
//! }
//!
//! public static int add(int a, int b) {
//! return a + b;
//! }
//!
//! public static String append(String input) {
//! return input + " there from Java!";
//! }
//!
//! public static void printMessage() {
//! System.out.println("The message is: " + message);
//! }
//!
//! public boolean allOnes(int iarr[]) {
//! final IntStream stream1 = Arrays.stream(iarr);
//! return stream1.allMatch(i -> i == 1);
//! }
//!
//! public int[] iArr() {
//! int[] a = {1,2,3,4,5,9};
//! return a;
//! }
//! }
//! ```
//!
//! ## Rust
//! ```
//! # #![feature(try_from)]
//! # #[macro_use] extern crate error_chain;
//! # extern crate rsjni;
//! #
//! # use rsjni::{array, Classpath, Input, strng, Version, Jvm, Kind, Opts};
//! # use std::convert::TryFrom;
//! # use std::env;
//! # use std::path::PathBuf;
//! #
//! # error_chain!{
//! # foreign_links {
//! # Var(::std::env::VarError);
//! # RsJni(::rsjni::Error);
//! # }
//! # }
//! #
//! # fn run() -> Result<()> {
//! // Setup the `Classpath`. These are the directories or jar files to search for .class files.
//! let manifest = env::var("CARGO_MANIFEST_DIR")?;
//! let path = PathBuf::from(manifest).join("examples");
//! let mut classpath: Classpath = Default::default();
//! classpath.add(path);
//!
//! // Setup the `Opts`, i.e. -Xms256m
//! let mut opts: Opts = Default::default();
//! opts.set_initial_heap_size(256);
//! opts.set_max_heap_size(256);
//! opts.set_version(Version::V18);
//! opts.set_classpath(classpath);
//!
//! // Create the JVM.
//! let jvm = Jvm::new(opts)?;
//!
//! // Get the JNI environment from the JVM.
//! let env = jvm.env();
//!
//! // Load the class `Test` into the JVM if it is found on the classpath.
//! let test_class = env.find_class("Test")?;
//!
//! // We are Java-ing. We need to construct an instance of our class.
//! //
//! // The proper constructor is found based on the argument signature, `Test(int)` in this case.
//! // We are trying to call `Test(5)` here, which stores 5 in the `current` field.
//! let constructor_id = test_class.get_method_id("<init>", &[Kind::Int], &Kind::Void)?;
//! let test_object = test_class.new_object(&constructor_id, &[Input::Int(5)])?;
//!
//! let inc_curr_method_id = test_class.get_method_id("incrementCurrent", &[], &Kind::Void)?;
//! // Lets change some internal state. Call 'public void incrementCurrent()'. Internally, the
//! // `incrementCurrent` method increments the `current` field by 1.
//! test_object.call_method(&inc_curr_method_id, &[])?;
//!
//! // Lets see what our `current` value is via a getter. Call 'public int getCurrent()'
//! let get_curr_method_id = test_class.get_method_id("getCurrent", &[], &Kind::Int)?;
//! let current = test_object.call_method(&get_curr_method_id, &[])?;
//! // Here we are converting the `Output` object into the type we expect.
//! assert_eq!(6, current.int());
//!
//! // Set the 'public int current' field to 10.
//! let current_field_id = test_class.get_field_id("current", &Kind::Int)?;
//! test_object.set_field(¤t_field_id, &Input::Int(10))?;
//!
//! // Read back the field to check that it is now 10.
//! let updated_current = test_object.get_field(¤t_field_id)?;
//! assert_eq!(10, updated_current.int());
//!
//! // Call 'public static int add(int a, int b)'.
//! // Notice that we call static methods on the class, not the object instance.
//! let args = [Input::Int(1), Input::Int(8)];
//! let add_method_id = test_class.get_static_method_id("add", &[Kind::Int, Kind::Int], &Kind::Int)?;
//! let value1 = test_class.call_static_method(&add_method_id, &args)?;
//! assert_eq!(9, value1.int());
//!
//! // Get the value of the 'public static String message' field.
//! let message_field_id = test_class.get_static_field_id("message", &Kind::Object("java/lang/String".to_string()))?;
//! let message = test_class.get_static_field(&message_field_id)?;
//! // Convert the output object into a string.
//! let java_str: strng::JavaString = TryFrom::try_from(message.object())?;
//! let message_str: String = TryFrom::try_from(java_str)?;
//! assert_eq!(message_str, "Hello!");
//!
//! // Set the value of the 'public static String message' field to "Hi!".
//! // We need to create the 'java/lang/String' in the JVM first.
//! let str_obj = strng::JavaString::new(&env, "Hi!")?;
//! test_class.set_static_field(&message_field_id, &Input::StringObj(str_obj))?;
//!
//! // Get the value again to see that the static field is changed.
//! let new_message = test_class.get_static_field(&message_field_id)?;
//! let java_str: strng::JavaString = TryFrom::try_from(new_message.object())?;
//! let new_message_str: String = TryFrom::try_from(java_str)?;
//! assert_eq!(new_message_str, "Hi!");
//!
//! // Work with an array input.
//! // Create an int[5] in the JVM.
//! let mut int_arr = array::Int::new(&env, 5)?;
//!
//! // Setup the array in the JVM.
//! int_arr.set_slice(0, &[1; 5])?;
//!
//! // Check that the array now contains all 1's.
//! let args = [Input::IntArr(int_arr)];
//! let all_ones_method_id = test_class.get_method_id("allOnes", &[Kind::IntArr], &Kind::Boolean)?;
//! let value = test_object.call_method(&all_ones_method_id, &args)?;
//! assert!(value.boolean());
//!
//! // Now we are calling a method that returns an int[].
//! let int_arr_method_id = test_class.get_method_id("intArr", &[], &Kind::IntArr)?;
//! let int_arr_ret = test_object.call_method(&int_arr_method_id, &[])?;
//! // Get the object out of the `Output`.
//! let int_arr: array::Int = TryFrom::try_from(int_arr_ret.object())?;
//!
//! // Convert it to an array we can work with.
//! let mut full_buf = [0; 6];
//! int_arr.as_slice(0, 6, &mut full_buf)?;
//!
//! // Release it back to the JVM to allow for GC.
//! drop(int_arr);
//!
//! # Ok(())
//! # }
//! # fn main() {
//! # run().expect("fail!");
//! # }
extern crate error_chain;
extern crate getset;
extern crate lazy_static;
extern crate core;
pub use ;
pub use Error;
pub use ;
pub use ;
pub use ;
pub use ;