pub mod arrays;
pub mod classcache;
pub mod exceptions;
pub mod future;
pub mod ops;
pub mod stream;
pub mod task;
pub mod uuid;
#[cfg(test)]
pub(crate) mod test_utils {
use jni::{JNIEnv, JavaVM, objects::GlobalRef};
use lazy_static::lazy_static;
use std::{
sync::{Arc, Mutex},
task::{Wake, Waker},
};
use jni::NativeMethod;
fn test_init(env: &JNIEnv) -> jni::errors::Result<()> {
use std::ffi::c_void;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/future/Future")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/future/FutureException")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/ops/FnAdapter")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/stream/Stream")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/stream/StreamPoll")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/task/Waker")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/task/PollResult")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/ops/FnRunnableImpl")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/ops/FnBiFunctionImpl")?;
super::classcache::find_add_class(env, "io/github/gedgygedgy/rust/ops/FnFunctionImpl")?;
let class = env.auto_local(env.find_class("io/github/gedgygedgy/rust/ops/FnAdapter")?);
env.register_native_methods(
&class,
&[
NativeMethod {
name: "callInternal".into(),
sig:
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"
.into(),
fn_ptr: super::ops::fn_adapter_call_internal as *mut c_void,
},
NativeMethod {
name: "closeInternal".into(),
sig: "()V".into(),
fn_ptr: super::ops::fn_adapter_close_internal as *mut c_void,
},
],
)?;
Ok(())
}
pub struct TestWakerData(Mutex<bool>);
impl TestWakerData {
pub fn new() -> Self {
Self(Mutex::new(false))
}
pub fn value(&self) -> bool {
*self.0.lock().unwrap()
}
pub fn set_value(&self, value: bool) {
let mut guard = self.0.lock().unwrap();
*guard = value;
}
}
impl Wake for TestWakerData {
fn wake(self: Arc<Self>) {
Self::wake_by_ref(&self);
}
fn wake_by_ref(self: &Arc<Self>) {
self.set_value(true);
}
}
pub fn test_waker(data: &Arc<TestWakerData>) -> Waker {
Waker::from(data.clone())
}
struct GlobalJVM {
jvm: JavaVM,
class_loader: GlobalRef,
}
thread_local! {
pub static JVM_ENV: JNIEnv<'static> = {
let env = JVM.jvm.attach_current_thread_permanently().unwrap();
let thread = env
.call_static_method(
"java/lang/Thread",
"currentThread",
"()Ljava/lang/Thread;",
&[],
)
.unwrap()
.l()
.unwrap();
env.call_method(
thread,
"setContextClassLoader",
"(Ljava/lang/ClassLoader;)V",
&[JVM.class_loader.as_obj().into()]
).unwrap();
env
}
}
lazy_static! {
static ref JVM: GlobalJVM = {
use jni::InitArgsBuilder;
use std::{env, path::PathBuf};
let mut jni_utils_jar = PathBuf::from(env::current_exe().unwrap());
jni_utils_jar.pop();
jni_utils_jar.pop();
jni_utils_jar.push("java");
jni_utils_jar.push("libs");
jni_utils_jar.push("btleplug-jni.jar");
let jvm_args = InitArgsBuilder::new()
.option(&format!(
"-Djava.class.path={}",
jni_utils_jar.to_str().unwrap()
))
.build()
.unwrap();
let jvm = JavaVM::new(jvm_args).unwrap();
let env = jvm.attach_current_thread_permanently().unwrap();
test_init(&env).unwrap();
let thread = env
.call_static_method(
"java/lang/Thread",
"currentThread",
"()Ljava/lang/Thread;",
&[],
)
.unwrap()
.l()
.unwrap();
let class_loader = env
.call_method(
thread,
"getContextClassLoader",
"()Ljava/lang/ClassLoader;",
&[],
)
.unwrap()
.l()
.unwrap();
let class_loader = env.new_global_ref(class_loader).unwrap();
GlobalJVM { jvm, class_loader }
};
}
}