feat: update toad-jni

This commit is contained in:
Orion Kindel 2023-04-08 10:35:23 -07:00
parent 7c96dd576b
commit 7eef137bcd
Signed by untrusted user who does not match committer: orion
GPG Key ID: 6D4165AE4C928719
15 changed files with 486 additions and 517 deletions

View File

@ -1,2 +1,2 @@
[build] [build]
target-dir = "../target/native" target-dir = "../target/glue"

28
glue/Cargo.lock generated
View File

@ -504,9 +504,9 @@ checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]] [[package]]
name = "toad" name = "toad"
version = "0.17.2" version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6e3e3216e542ea3b2da0d2200e498b016907b68acb288b47a487cb9fd681b42" checksum = "5d4000090e5f6d1380e1a4bfb9a5428019cb7a4374b3663792ef7965384968fc"
dependencies = [ dependencies = [
"embedded-time", "embedded-time",
"log", "log",
@ -525,7 +525,7 @@ dependencies = [
"toad-len", "toad-len",
"toad-macros", "toad-macros",
"toad-map", "toad-map",
"toad-msg 0.15.1", "toad-msg",
"toad-stem", "toad-stem",
"toad-writable", "toad-writable",
] ]
@ -570,17 +570,18 @@ name = "toad-java-glue"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"jni", "jni",
"nb",
"tinyvec", "tinyvec",
"toad", "toad",
"toad-jni", "toad-jni",
"toad-msg 0.18.1", "toad-msg",
] ]
[[package]] [[package]]
name = "toad-jni" name = "toad-jni"
version = "0.4.1" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff5fbc1fb554ad85160c74d6c6db551f164b79917c89509037477ad308d2b4ac" checksum = "9d47119dc7ecc1c65fa860a7b2c95dd45b177d07331ee8a18cac0cc41c9bd825"
dependencies = [ dependencies = [
"jni", "jni",
"toad-array 0.5.0", "toad-array 0.5.0",
@ -618,21 +619,6 @@ dependencies = [
"toad-len", "toad-len",
] ]
[[package]]
name = "toad-msg"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "172e73f5ce192a45314eef776dd7e1e3cbde1c51ea021d79ac3630549925fbe5"
dependencies = [
"blake2",
"tinyvec",
"toad-array 0.2.3",
"toad-cursor",
"toad-len",
"toad-macros",
"toad-map",
]
[[package]] [[package]]
name = "toad-msg" name = "toad-msg"
version = "0.18.1" version = "0.18.1"

View File

@ -9,7 +9,8 @@ crate_type = ["cdylib"]
[dependencies] [dependencies]
jni = "0.21.1" jni = "0.21.1"
toad = "0.17.2" nb = "1"
toad-jni = "0.4.1" toad = "0.17.3"
toad-jni = "0.5.1"
toad-msg = "0.18.1" toad-msg = "0.18.1"
tinyvec = {version = "1.5", default_features = false, features = ["rustc_1_55"]} tinyvec = {version = "1.5", default_features = false, features = ["rustc_1_55"]}

View File

@ -1,15 +1,7 @@
#![feature(strict_provenance)] #![feature(strict_provenance)]
use jni::objects::{JClass, JObject}; pub type Runtime =
use jni::JNIEnv; toad::std::Platform<toad::std::dtls::N, toad::step::runtime::std::Runtime<toad::std::dtls::N>>;
use toad::std::{dtls, Platform as Std};
use toad::step::runtime::std::Runtime;
pub static mut RUNTIME: *const Std<dtls::N, Runtime<dtls::N>> = std::ptr::null();
pub unsafe fn with_runtime_provenance<T>(addr: i64) -> *mut T {
RUNTIME.with_addr(addr as usize).cast::<T>().cast_mut()
}
#[macro_export] #[macro_export]
macro_rules! package { macro_rules! package {
@ -18,33 +10,31 @@ macro_rules! package {
(ext $start:ident.$($thing:ident).+) => {concat!(stringify!($start), $("/", stringify!($thing)),+)}; (ext $start:ident.$($thing:ident).+) => {concat!(stringify!($start), $("/", stringify!($thing)),+)};
} }
pub mod mem;
pub mod message_code; pub mod message_code;
pub mod message_opt_ref; pub mod message_opt_ref;
pub mod message_opt_value_ref; pub mod message_opt_value_ref;
pub mod message_ref; pub mod message_ref;
pub mod message_type; pub mod message_type;
pub mod retry_strategy; pub mod retry_strategy;
pub mod runtime;
pub mod runtime_config; pub mod runtime_config;
pub mod uint; pub mod uint;
pub extern "system" fn Java_dev_toad_Runtime_init<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
cfg: JObject<'local>) {
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Once; use std::sync::Once;
use jni::{InitArgsBuilder, JNIEnv, JavaVM}; use jni::{InitArgsBuilder, JavaVM};
use toad::retry::Strategy; use toad::retry::Strategy;
use toad::time::Millis; use toad::time::Millis;
use toad_jni::java;
use crate::retry_strategy::RetryStrategy; use crate::retry_strategy::RetryStrategy;
use crate::runtime_config::RuntimeConfig; use crate::runtime_config::RuntimeConfig;
static INIT: Once = Once::new(); static INIT: Once = Once::new();
pub fn init<'a>() -> JNIEnv<'a> { pub fn init<'a>() -> java::Env<'a> {
INIT.call_once(|| { INIT.call_once(|| {
let jvm = let jvm =
JavaVM::new(InitArgsBuilder::new().option("--enable-preview") JavaVM::new(InitArgsBuilder::new().option("--enable-preview")
@ -54,8 +44,9 @@ mod tests {
toad_jni::global::init_with(jvm); toad_jni::global::init_with(jvm);
}); });
toad_jni::global::jvm().attach_current_thread_permanently(); toad_jni::global::jvm().attach_current_thread_permanently()
toad_jni::global::env() .unwrap();
toad_jni::global::jvm().get_env().unwrap()
} }
#[test] #[test]

50
glue/src/mem.rs Normal file
View File

@ -0,0 +1,50 @@
/// global [`RuntimeAllocator`] implementation
pub type Runtime = RuntimeGlobalStaticAllocator;
/// Trait managing the memory region(s) associated with the toad runtime
/// data structure.
///
/// Notably, any and all references produced by the runtime will be to data
/// within the Runtime's memory region, meaning that we can easily leverage
/// strict provenance to prevent addresses from leaking outside of that memory region.
pub trait RuntimeAllocator: core::default::Default + core::fmt::Debug + Copy {
/// Allocate memory for the runtime and yield a stable pointer to it
unsafe fn alloc(r: crate::Runtime) -> *mut crate::Runtime;
/// Coerce a `long` rep of the stable pointer created by [`Self::alloc`] to
/// a pointer (preferably using strict_provenance)
unsafe fn deref(addr: i64) -> *mut crate::Runtime;
/// Coerce a `long` rep of a pointer to some data within the
/// Runtime data structure.
///
/// Requires the Runtime address in order for the new pointer
/// to inherit its provenance.
unsafe fn deref_inner<T>(runtime_addr: i64, addr: i64) -> *mut T {
Self::deref(runtime_addr).with_addr(addr as usize)
.cast::<T>()
}
}
static mut RUNTIME: *mut crate::Runtime = core::ptr::null_mut();
#[derive(Default, Debug, Clone, Copy)]
pub struct RuntimeGlobalStaticAllocator;
impl RuntimeAllocator for RuntimeGlobalStaticAllocator {
/// Nops on already-init
unsafe fn alloc(r: crate::Runtime) -> *mut crate::Runtime {
if RUNTIME.is_null() {
let p =
std::alloc::alloc(std::alloc::Layout::new::<crate::Runtime>()).cast::<crate::Runtime>();
*p = r;
RUNTIME = p;
RUNTIME
} else {
RUNTIME
}
}
unsafe fn deref(_: i64) -> *mut crate::Runtime {
RUNTIME
}
}

View File

@ -1,19 +1,16 @@
use jni::objects::{JClass, JObject}; use toad_jni::java;
use jni::sys::jobject;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::Code; use toad_msg::Code;
pub struct MessageCode<'local>(pub JObject<'local>); pub struct MessageCode(java::lang::Object);
impl<'local> MessageCode<'local> {
const ID: &'static str = package!(dev.toad.msg.MessageCode);
const CTOR: Sig = Sig::new().arg(Sig::INT).arg(Sig::INT).returning(Sig::VOID);
pub fn new(env: &mut JNIEnv<'local>, code: Code) -> Self { java::object_newtype!(MessageCode);
let o = env.new_object(Self::ID, impl java::Class for MessageCode {
Self::CTOR, const PATH: &'static str = package!(dev.toad.msg.MessageCode);
&[i32::from(code.class).into(), i32::from(code.detail).into()]) }
.unwrap();
Self(o) impl MessageCode {
pub fn new(e: &mut java::Env, code: Code) -> Self {
static CTOR: java::Constructor<MessageCode, fn(i32, i32)> = java::Constructor::new();
CTOR.invoke(e, code.class.into(), code.detail.into())
} }
} }

View File

@ -1,41 +1,34 @@
use jni::objects::{JClass, JObject}; use jni::objects::{JClass, JObject};
use jni::sys::jobject; use jni::sys::jobject;
use jni::JNIEnv; use jni::JNIEnv;
use toad_jni::Sig; use toad_jni::java::{self, Object};
use toad_msg::{OptNumber, OptValue}; use toad_msg::{OptNumber, OptValue};
use crate::mem::RuntimeAllocator;
use crate::message_opt_value_ref::MessageOptValueRef; use crate::message_opt_value_ref::MessageOptValueRef;
use crate::with_runtime_provenance;
pub struct MessageOptRef<'local>(pub JObject<'local>); pub struct MessageOptRef(pub java::lang::Object);
impl<'local> MessageOptRef<'local> {
const ID: &'static str = package!(dev.toad.msg.MessageOptionRef);
const CTOR: Sig = Sig::new().arg(Sig::LONG)
.arg(Sig::LONG)
.returning(Sig::VOID);
const NUMBER: &'static str = "number"; java::object_newtype!(MessageOptRef);
pub fn class(env: &mut JNIEnv<'local>) -> JClass<'local> { impl java::Class for MessageOptRef {
env.find_class(Self::ID).unwrap() const PATH: &'static str = package!(dev.toad.msg.MessageOptionRef);
}
impl MessageOptRef {
pub fn new(env: &mut java::Env, addr: i64, num: i64) -> Self {
static CTOR: java::Constructor<MessageOptRef, fn(i64, i64)> = java::Constructor::new();
CTOR.invoke(env, addr, num)
} }
pub fn new(env: &mut JNIEnv<'local>, addr: i64, num: i64) -> Self { pub fn number(&self, env: &mut java::Env) -> OptNumber {
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into(), num.into()]) static NUMBER: java::Field<MessageOptRef, i64> = java::Field::new("number");
.unwrap(); OptNumber(NUMBER.get(env, self) as u32)
Self(o)
}
pub fn number(&self, env: &mut JNIEnv<'local>) -> OptNumber {
OptNumber(env.get_field(&self.0, Self::NUMBER, Sig::LONG)
.unwrap()
.j()
.unwrap() as u32)
} }
pub unsafe fn values_ptr<'a>(addr: i64) -> &'a mut Vec<OptValue<Vec<u8>>> { pub unsafe fn values_ptr<'a>(addr: i64) -> &'a mut Vec<OptValue<Vec<u8>>> {
with_runtime_provenance::<Vec<OptValue<Vec<u8>>>>(addr).as_mut() crate::mem::Runtime::deref_inner::<Vec<OptValue<Vec<u8>>>>(/* TODO */ 0, addr).as_mut()
.unwrap() .unwrap()
} }
} }
@ -44,24 +37,21 @@ pub extern "system" fn Java_dev_toad_msg_MessageOptionRef_number<'local>(mut env
o: JObject<'local>, o: JObject<'local>,
p: i64) p: i64)
-> i64 { -> i64 {
MessageOptRef(o).number(&mut env).0 as i64 java::lang::Object::from_local(&mut env, o).upcast_to::<MessageOptRef>(&mut env)
.number(&mut env)
.0 as i64
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageOptionRef_values<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageOptionRef_values<'local>(mut e: JNIEnv<'local>,
_: JClass<'local>, _: JClass<'local>,
p: i64) p: i64)
-> jobject { -> jobject {
let o = &unsafe { MessageOptRef::values_ptr(p) }; let o = &unsafe { MessageOptRef::values_ptr(p) };
let value_ref_class = MessageOptValueRef::class(&mut env); let refs = o.iter()
let mut arr = env.new_object_array(o.len() as i32, value_ref_class, JObject::null()) .map(|v| MessageOptValueRef::new(&mut e, (&v.0 as *const Vec<u8>).addr() as i64))
.unwrap(); .collect::<Vec<_>>();
for (ix, v) in o.iter().enumerate() { refs.downcast(&mut e).as_raw()
let value_ref = MessageOptValueRef::new(&mut env, v as *const _ as i64);
env.set_object_array_element(&mut arr, ix as i32, value_ref.0);
}
arr.as_raw()
} }

View File

@ -1,34 +1,31 @@
use jni::objects::{JClass, JObject}; use jni::objects::JClass;
use jni::sys::jobject; use jni::sys::jobject;
use jni::JNIEnv; use toad_jni::java;
use toad_jni::Sig; use toad_msg::OptValue;
use toad_msg::{OptNumber, OptValue};
use crate::with_runtime_provenance; use crate::mem::RuntimeAllocator;
pub struct MessageOptValueRef<'local>(pub JObject<'local>); pub struct MessageOptValueRef(java::lang::Object);
impl<'local> MessageOptValueRef<'local> {
const ID: &'static str = package!(dev.toad.msg.MessageOptionValueRef);
const CTOR: Sig = Sig::new().arg(Sig::LONG).returning(Sig::VOID);
pub fn class(env: &mut JNIEnv<'local>) -> JClass<'local> { java::object_newtype!(MessageOptValueRef);
env.find_class(Self::ID).unwrap() impl java::Class for MessageOptValueRef {
} const PATH: &'static str = package!(dev.toad.msg.MessageOptionValueRef);
}
pub fn new(env: &mut JNIEnv<'local>, addr: i64) -> Self { impl MessageOptValueRef {
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into()]) pub fn new(env: &mut java::Env, addr: i64) -> Self {
.unwrap(); static CTOR: java::Constructor<MessageOptValueRef, fn(i64)> = java::Constructor::new();
Self(o) CTOR.invoke(env, addr)
} }
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut OptValue<Vec<u8>> { pub unsafe fn ptr<'a>(addr: i64) -> &'a mut OptValue<Vec<u8>> {
with_runtime_provenance::<OptValue<Vec<u8>>>(addr).as_mut() crate::mem::Runtime::deref_inner::<OptValue<Vec<u8>>>(/* TODO */ 0, addr).as_mut()
.unwrap() .unwrap()
} }
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageOptionValueRef_bytes<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageOptionValueRef_bytes<'local>(mut env: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
p: i64) p: i64)
-> jobject { -> jobject {

View File

@ -1,32 +1,34 @@
use jni::objects::{JClass, JObject}; use jni::objects::JClass;
use jni::sys::jobject; use jni::sys::jobject;
use jni::JNIEnv; use toad_jni::java::{self, Object};
use toad_jni::Sig;
use toad_msg::alloc::Message; use toad_msg::alloc::Message;
use crate::mem::RuntimeAllocator;
use crate::message_code::MessageCode; use crate::message_code::MessageCode;
use crate::message_opt_ref::MessageOptRef; use crate::message_opt_ref::MessageOptRef;
use crate::message_type::MessageType; use crate::message_type::MessageType;
use crate::{with_runtime_provenance, RUNTIME};
pub struct MessageRef<'local>(pub JObject<'local>); pub struct MessageRef(java::lang::Object);
impl<'local> MessageRef<'local> {
const ID: &'static str = package!(dev.toad.msg.MessageRef);
const CTOR: Sig = Sig::new().arg(Sig::LONG).returning(Sig::VOID);
pub fn new(env: &mut JNIEnv<'local>, addr: i64) -> Self { java::object_newtype!(MessageRef);
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into()]) impl java::Class for MessageRef {
.unwrap(); const PATH: &'static str = package!(dev.toad.msg.MessageRef);
Self(o) }
impl MessageRef {
pub fn new(env: &mut java::Env, addr: *const Message) -> Self {
static CTOR: java::Constructor<MessageRef, fn(i64)> = java::Constructor::new();
CTOR.invoke(env, addr.addr() as i64)
} }
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut Message { pub unsafe fn ptr<'a>(addr: i64) -> &'a mut Message {
with_runtime_provenance::<Message>(addr).as_mut().unwrap() crate::mem::Runtime::deref_inner::<Message>(/* TODO */ 0, addr).as_mut()
.unwrap()
} }
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_id<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_id<'local>(mut env: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> i32 { -> i32 {
@ -35,7 +37,7 @@ pub extern "system" fn Java_dev_toad_msg_MessageRef_id<'local>(mut env: JNIEnv<'
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_token<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_token<'local>(mut env: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> jobject { -> jobject {
@ -44,7 +46,7 @@ pub extern "system" fn Java_dev_toad_msg_MessageRef_token<'local>(mut env: JNIEn
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_payload<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_payload<'local>(mut env: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> jobject { -> jobject {
@ -53,39 +55,34 @@ pub extern "system" fn Java_dev_toad_msg_MessageRef_payload<'local>(mut env: JNI
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_type<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_type<'local>(mut e: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> jobject { -> jobject {
let msg = unsafe { MessageRef::ptr(addr) }; let msg = unsafe { MessageRef::ptr(addr) };
MessageType::new(&mut env, msg.ty).0.into_raw() MessageType::new(&mut e, msg.ty).downcast(&mut e).as_raw()
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_code<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_code<'local>(mut e: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> jobject { -> jobject {
let msg = unsafe { MessageRef::ptr(addr) }; let msg = unsafe { MessageRef::ptr(addr) };
MessageCode::new(&mut env, msg.code).0.into_raw() MessageCode::new(&mut e, msg.code).downcast(&mut e).as_raw()
} }
#[no_mangle] #[no_mangle]
pub extern "system" fn Java_dev_toad_msg_MessageRef_opts<'local>(mut env: JNIEnv<'local>, pub extern "system" fn Java_dev_toad_msg_MessageRef_opts<'local>(mut e: java::Env<'local>,
_: JClass<'local>, _: JClass<'local>,
addr: i64) addr: i64)
-> jobject { -> jobject {
let msg = unsafe { MessageRef::ptr(addr) }; let msg = unsafe { MessageRef::ptr(addr) };
let opts = &msg.opts; let opts = &msg.opts;
let opt_ref_class = MessageOptRef::class(&mut env); let refs = opts.into_iter()
let mut arr = env.new_object_array((*opts).len() as i32, opt_ref_class, JObject::null()) .map(|(n, v)| MessageOptRef::new(&mut e, v as *const _ as i64, n.0.into()))
.unwrap(); .collect::<Vec<_>>();
for (ix, (num, v)) in (*opts).iter().enumerate() { refs.downcast(&mut e).as_raw()
let opt_ref = MessageOptRef::new(&mut env, v as *const _ as i64, num.0.into());
env.set_object_array_element(&mut arr, ix as i32, opt_ref.0);
}
arr.as_raw()
} }

View File

@ -1,32 +1,25 @@
use jni::objects::{JObject, JString, JValueGen}; use toad_jni::java;
use jni::sys::jstring;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::Type; use toad_msg::Type;
pub struct MessageType<'local>(pub JObject<'local>); pub struct MessageType(java::lang::Object);
impl<'local> MessageType<'local> {
const ID: &'static str = package!(dev.toad.msg.MessageType);
const FROM_STRING: Sig = Sig::new().arg(Sig::class("java/lang/String"))
.returning(Sig::class(Self::ID));
pub fn new(env: &mut JNIEnv<'local>, ty: Type) -> Self { java::object_newtype!(MessageType);
let str = env.new_string(match ty { impl java::Class for MessageType {
| Type::Con => "CON", const PATH: &'static str = package!(dev.toad.msg.MessageType);
| Type::Non => "NON", }
| Type::Ack => "ACK",
| Type::Reset => "RESET",
})
.unwrap();
let o = env.call_static_method(Self::ID, impl MessageType {
"fromString", pub fn new(env: &mut java::Env, ty: Type) -> Self {
Self::FROM_STRING, static FROM_STRING: java::StaticMethod<MessageType, fn(String) -> MessageType> =
&[JValueGen::Object(&str)]) java::StaticMethod::new("fromString");
.unwrap()
.l()
.unwrap();
Self(o) let str = match ty {
| Type::Con => "CON",
| Type::Non => "NON",
| Type::Ack => "ACK",
| Type::Reset => "RESET",
};
FROM_STRING.invoke(env, str.to_string())
} }
} }

View File

@ -1,89 +1,103 @@
use jni::objects::{GlobalRef, JObject};
use jni::JNIEnv;
use toad::retry::Strategy; use toad::retry::Strategy;
use toad::time::Millis; use toad::time::Millis;
use toad_jni::cls::java; use toad_jni::java::{self, Object};
use toad_jni::convert::Object;
use toad_jni::Sig;
use crate::uint; use crate::uint;
pub struct RetryStrategy(GlobalRef); pub struct RetryStrategyExp(java::lang::Object);
java::object_newtype!(RetryStrategyExp);
impl java::Class for RetryStrategyExp {
const PATH: &'static str = package!(dev.toad.RetryStrategyExponential);
}
impl RetryStrategyExp {
pub fn new(e: &mut java::Env, init_min: Millis, init_max: Millis) -> Self {
let (init_min, init_max) = (java::time::Duration::of_millis(e, init_min.0 as i64),
java::time::Duration::of_millis(e, init_max.0 as i64));
static CTOR: java::Constructor<RetryStrategyExp,
fn(java::time::Duration, java::time::Duration)> =
java::Constructor::new();
CTOR.invoke(e, init_min, init_max)
}
pub fn as_super(self) -> RetryStrategy {
RetryStrategy(self.0)
}
pub fn init_min(&self, e: &mut java::Env) -> Millis {
static INIT_MIN: java::Field<RetryStrategyExp, uint::u64> = java::Field::new("initMin");
Millis::new(INIT_MIN.get(e, self).to_rust(e))
}
pub fn init_max(&self, e: &mut java::Env) -> Millis {
static INIT_MAX: java::Field<RetryStrategyExp, uint::u64> = java::Field::new("initMax");
Millis::new(INIT_MAX.get(e, self).to_rust(e))
}
}
pub struct RetryStrategyDelay(java::lang::Object);
java::object_newtype!(RetryStrategyDelay);
impl java::Class for RetryStrategyDelay {
const PATH: &'static str = package!(dev.toad.RetryStrategyDelay);
}
impl RetryStrategyDelay {
pub fn new(e: &mut java::Env, min: Millis, max: Millis) -> Self {
let (min, max) = (java::time::Duration::of_millis(e, min.0 as i64),
java::time::Duration::of_millis(e, max.0 as i64));
static CTOR: java::Constructor<RetryStrategyDelay,
fn(java::time::Duration, java::time::Duration)> =
java::Constructor::new();
CTOR.invoke(e, min, max)
}
pub fn as_super(self) -> RetryStrategy {
RetryStrategy(self.0)
}
pub fn min(&self, e: &mut java::Env) -> Millis {
static MIN: java::Field<RetryStrategyDelay, uint::u64> = java::Field::new("min");
Millis::new(MIN.get(e, self).to_rust(e))
}
pub fn max(&self, e: &mut java::Env) -> Millis {
static MAX: java::Field<RetryStrategyDelay, uint::u64> = java::Field::new("max");
Millis::new(MAX.get(e, self).to_rust(e))
}
}
pub struct RetryStrategy(java::lang::Object);
java::object_newtype!(RetryStrategy);
impl java::Class for RetryStrategy {
const PATH: &'static str = package!(dev.toad.RetryStrategy);
}
impl RetryStrategy { impl RetryStrategy {
pub const PATH: &'static str = package!(dev.toad.RetryStrategy); pub fn to_toad(self, e: &mut java::Env) -> Strategy {
if self.0.is_instance_of::<RetryStrategyExp>(e) {
pub const EXPONENTIAL: &'static str = package!(dev.toad.RetryStrategyExponential); let me = RetryStrategyExp(self.0);
pub const EXPONENTIAL_CTOR: Sig = Sig::new().arg(Sig::class(java::time::Duration::PATH)) Strategy::Exponential { init_min: me.init_min(e),
.arg(Sig::class(java::time::Duration::PATH)) init_max: me.init_max(e) }
.returning(Sig::VOID); } else if self.0.is_instance_of::<RetryStrategyDelay>(e) {
let me = RetryStrategyDelay(self.0);
pub const DELAY: &'static str = package!(dev.toad.RetryStrategyDelay); Strategy::Delay { min: me.min(e),
pub const DELAY_CTOR: Sig = Sig::new().arg(Sig::class(java::time::Duration::PATH)) max: me.max(e) }
.arg(Sig::class(java::time::Duration::PATH))
.returning(Sig::VOID);
pub fn exp<'a>(&self, e: &mut JNIEnv<'a>) -> Self {
let o = e.new_object(Self::PATH, Sig::new().returning(Sig::VOID), &[])
.unwrap();
let g = e.new_global_ref(o).unwrap();
Self(g)
}
pub fn millis_field<'a>(&self, e: &mut JNIEnv<'a>, key: &str) -> Millis {
let o = e.get_field(&self.0, key, Sig::class(uint::u64::PATH))
.unwrap()
.l()
.unwrap();
let g = e.new_global_ref(o).unwrap();
let d = uint::u64::from_java(g);
Millis::new(d.to_rust(e))
}
pub fn to_toad<'a>(self, e: &mut JNIEnv<'a>) -> Strategy {
if e.is_instance_of(&self.0, Self::EXPONENTIAL).unwrap() {
Strategy::Exponential { init_min: self.millis_field(e, "initMin"),
init_max: self.millis_field(e, "initMax") }
} else { } else {
Strategy::Delay { min: self.millis_field(e, "min"), let cls = e.get_object_class(self.0).unwrap();
max: self.millis_field(e, "max") } panic!("unknown inheritor of RetryStrategy: {}",
java::lang::Object::from_local(e, cls).to_string(e));
} }
} }
pub fn from_toad<'a>(e: &mut JNIEnv<'a>, s: Strategy) -> Self { pub fn from_toad(e: &mut java::Env, s: Strategy) -> Self {
let g = match s { match s {
| Strategy::Delay { min, max } => { | Strategy::Delay { min, max } => RetryStrategyDelay::new(e, min, max).as_super(),
let (min, max) = (java::time::Duration::of_millis(e, min.0 as i64),
java::time::Duration::of_millis(e, max.0 as i64));
let (min, max) = (min.to_java(), max.to_java());
let o = e.new_object(Self::DELAY,
Self::DELAY_CTOR,
&[min.as_obj().into(), max.as_obj().into()])
.unwrap();
e.new_global_ref(o).unwrap()
},
| Strategy::Exponential { init_min, init_max } => { | Strategy::Exponential { init_min, init_max } => {
let (init_min, init_max) = (java::time::Duration::of_millis(e, init_min.0 as i64), RetryStrategyExp::new(e, init_min, init_max).as_super()
java::time::Duration::of_millis(e, init_max.0 as i64));
let (init_min, init_max) = (init_min.to_java(), init_max.to_java());
let o = e.new_object(Self::EXPONENTIAL,
Self::EXPONENTIAL_CTOR,
&[init_min.as_obj().into(), init_max.as_obj().into()])
.unwrap();
e.new_global_ref(o).unwrap()
}, },
}; }
Self(g)
}
}
impl Object for RetryStrategy {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
} }
} }

69
glue/src/runtime.rs Normal file
View File

@ -0,0 +1,69 @@
use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use toad::platform::Platform;
use toad_jni::java::{self, Object};
use crate::mem::RuntimeAllocator;
use crate::message_ref::MessageRef;
use crate::runtime_config::RuntimeConfig;
use crate::Runtime as ToadRuntime;
pub struct Runtime(java::lang::Object);
impl Runtime {
pub fn init(e: &mut java::Env, cfg: RuntimeConfig) -> i64 {
let r =
ToadRuntime::try_new(format!("0.0.0.0:{}", cfg.net(e).port(e)), cfg.to_toad(e)).unwrap();
unsafe { crate::mem::Runtime::alloc(r).addr() as i64 }
}
pub fn addr(&self, e: &mut java::Env) -> i64 {
static ADDR: java::Field<Runtime, i64> = java::Field::new("addr");
ADDR.get(e, self)
}
pub fn ref_(&self, e: &mut java::Env) -> &'static ToadRuntime {
unsafe { crate::mem::Runtime::deref(self.addr(e)).as_ref().unwrap() }
}
}
java::object_newtype!(Runtime);
impl java::Class for Runtime {
const PATH: &'static str = package!(dev.toad.Runtime);
}
#[no_mangle]
pub extern "system" fn Java_dev_toad_Runtime_init<'local>(mut e: java::Env<'local>,
_: JClass<'local>,
cfg: JObject<'local>)
-> i64 {
let e = &mut e;
let cfg = java::lang::Object::from_local(e, cfg).upcast_to::<RuntimeConfig>(e);
Runtime::init(e, cfg)
}
// JNIEXPORT jobject JNICALL Java_dev_toad_Runtime_pollReq
// (JNIEnv *, jobject, jobject);
#[no_mangle]
pub extern "system" fn Java_dev_toad_Runtime_pollReq<'local>(mut e: java::Env<'local>,
runtime: JObject<'local>,
cfg: JObject<'local>)
-> jobject {
let e = &mut e;
let runtime = java::lang::Object::from_local(e, runtime).upcast_to::<Runtime>(e);
match runtime.ref_(e).poll_req() {
| Ok(req) => {
let mr = MessageRef::new(e, req.data().msg());
java::util::Optional::<MessageRef>::of(e, mr).downcast(e)
.as_raw()
},
| Err(nb::Error::WouldBlock) => java::util::Optional::<MessageRef>::empty(e).downcast(e)
.as_raw(),
| Err(nb::Error::Other(err)) => {
e.throw(format!("{:?}", err)).unwrap();
core::ptr::null_mut()
},
}
}

View File

@ -1,39 +1,29 @@
use jni::objects::{GlobalRef, JObject};
use jni::sys::{jint, jshort};
use jni::JNIEnv;
use toad::config::{self, BytesPerSecond}; use toad::config::{self, BytesPerSecond};
use toad::retry::{Attempts, Strategy}; use toad::retry::{Attempts, Strategy};
use toad::time::Millis; use toad::time::Millis;
use toad_jni::cls::java; use toad_jni::java;
use toad_jni::convert::{Object, Primitive};
use toad_jni::Sig;
use crate::retry_strategy::RetryStrategy; use crate::retry_strategy::RetryStrategy;
pub struct RuntimeConfig<'a>(JObject<'a>); pub struct RuntimeConfig(java::lang::Object);
impl<'a> RuntimeConfig<'a> { java::object_newtype!(RuntimeConfig);
pub const PATH: &'static str = package!(dev.toad.RuntimeOptions); impl java::Class for RuntimeConfig {
const PATH: &'static str = package!(dev.toad.RuntimeOptions);
}
pub const CTOR: Sig = Sig::new().returning(Sig::VOID); impl RuntimeConfig {
pub fn new(e: &mut java::Env) -> Self {
pub fn new(e: &mut JNIEnv<'a>) -> Self { static CTOR: java::Constructor<RuntimeConfig, fn()> = java::Constructor::new();
let o = e.new_object(Self::PATH, Self::CTOR, &[]).unwrap(); CTOR.invoke(e)
Self(o)
} }
pub fn net(&self, e: &mut JNIEnv<'a>) -> Net<'a> { pub fn net(&self, e: &mut java::Env) -> Net {
let o = e.call_method(&self.0, static NET: java::Method<RuntimeConfig, fn() -> Net> = java::Method::new("net");
"net", NET.invoke(e, self)
Sig::new().returning(Sig::class(Net::PATH)),
&[])
.unwrap()
.l()
.unwrap();
Net(o)
} }
pub fn to_toad(&self, e: &mut JNIEnv<'a>) -> config::Config { pub fn to_toad(&self, e: &mut java::Env) -> config::Config {
let def = config::Config::default(); let def = config::Config::default();
let net = self.net(e); let net = self.net(e);
@ -78,182 +68,121 @@ impl<'a> RuntimeConfig<'a> {
} }
} }
pub struct Net<'a>(JObject<'a>); pub struct Net(java::lang::Object);
impl<'a> Net<'a> { java::object_newtype!(Net);
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Net"); impl java::Class for Net {
const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Net");
}
pub fn port(&self, e: &mut JNIEnv<'a>) -> jshort { impl Net {
e.call_method(&self.0, "port", Sig::new().returning(Sig::SHORT), &[]) pub fn port(&self, e: &mut java::Env) -> i16 {
.unwrap() static PORT: java::Method<Net, fn() -> i16> = java::Method::new("port");
.s() PORT.invoke(e, self)
.unwrap()
} }
pub fn concurrency(&self, e: &mut JNIEnv<'a>) -> jshort { pub fn concurrency(&self, e: &mut java::Env) -> i16 {
e.call_method(&self.0, static CONCURRENCY: java::Method<Net, fn() -> i16> = java::Method::new("concurrency");
"concurrency", CONCURRENCY.invoke(e, self)
Sig::new().returning(Sig::SHORT),
&[])
.unwrap()
.s()
.unwrap()
} }
pub fn msg(&self, e: &mut JNIEnv<'a>) -> Msg<'a> { pub fn msg(&self, e: &mut java::Env) -> Msg {
let o = e.call_method(&self.0, static MSG: java::Method<Net, fn() -> Msg> = java::Method::new("msg");
"msg", MSG.invoke(e, self)
Sig::new().returning(Sig::class(Msg::PATH)),
&[])
.unwrap()
.l()
.unwrap();
Msg(o)
} }
} }
pub struct Msg<'a>(JObject<'a>); pub struct Msg(java::lang::Object);
impl<'a> Msg<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg");
pub const TOKEN_SEED: Sig = Sig::new().returning(Sig::class(java::util::Optional::<jint>::PATH)); java::object_newtype!(Msg);
pub const PROBING_RATE: Sig =
Sig::new().returning(Sig::class(java::util::Optional::<jint>::PATH));
pub const MULTICAST_RESP_LEISURE: Sig =
Sig::new().returning(Sig::class(java::util::Optional::<GlobalRef>::PATH));
pub const CON: Sig = Sig::new().returning(Sig::class(Con::PATH));
pub const NON: Sig = Sig::new().returning(Sig::class(Non::PATH));
pub fn token_seed(&self, e: &mut JNIEnv<'a>) -> Option<jint> { impl java::Class for Msg {
let o = e.call_method(&self.0, "tokenSeed", Self::TOKEN_SEED, &[]) const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg");
.unwrap() }
.l()
.unwrap(); impl Msg {
let g = e.new_global_ref(o).unwrap(); pub fn token_seed(&self, e: &mut java::Env) -> Option<i32> {
java::util::Optional::<jint>::from_java(g).to_option(e) static TOKEN_SEED: java::Method<Msg, fn() -> java::util::Optional<i32>> =
java::Method::new("tokenSeed");
TOKEN_SEED.invoke(e, self).to_option(e)
} }
pub fn probing_rate(&self, e: &mut JNIEnv<'a>) -> Option<jint> { pub fn probing_rate(&self, e: &mut java::Env) -> Option<i32> {
let o = e.call_method(&self.0, static PROBING_RATE: java::Method<Msg, fn() -> java::util::Optional<i32>> =
"probingRateBytesPerSecond", java::Method::new("probingRateBytesPerSecond");
Self::PROBING_RATE, PROBING_RATE.invoke(e, self).to_option(e)
&[])
.unwrap()
.l()
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<jint>::from_java(g).to_option(e)
} }
pub fn multicast_response_leisure(&self, e: &mut JNIEnv<'a>) -> Option<Millis> { pub fn multicast_response_leisure(&self, e: &mut java::Env) -> Option<Millis> {
let o = e.call_method(&self.0, static MULTICAST_RESP_LEISURE: java::Method<Msg,
"multicastResponseLeisure", fn()
Self::MULTICAST_RESP_LEISURE, -> java::util::Optional<java::time::Duration>> =
&[]) java::Method::new("multicastResponseLeisure");
.unwrap() MULTICAST_RESP_LEISURE.invoke(e, self)
.l() .to_option(e)
.unwrap(); .map(|d| Millis::new(d.to_millis(e) as u64))
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<GlobalRef>::from_java(g).to_option(e)
.map(java::time::Duration::from_java)
.map(|d| Millis::new(d.to_millis(e) as u64))
} }
pub fn con(&self, e: &mut JNIEnv<'a>) -> Con<'a> { pub fn con(&self, e: &mut java::Env) -> Con {
let o = e.call_method(&self.0, "con", Self::CON, &[]) static CON: java::Method<Msg, fn() -> Con> = java::Method::new("con");
.unwrap() CON.invoke(e, self)
.l()
.unwrap();
Con(o)
} }
pub fn non(&self, e: &mut JNIEnv<'a>) -> Non<'a> { pub fn non(&self, e: &mut java::Env) -> Non {
let o = e.call_method(&self.0, "non", Self::NON, &[]) static NON: java::Method<Msg, fn() -> Non> = java::Method::new("non");
.unwrap() NON.invoke(e, self)
.l()
.unwrap();
Non(o)
} }
} }
pub struct Con<'a>(JObject<'a>); pub struct Con(java::lang::Object);
impl<'a> Con<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Con");
pub const ACKED_RETRY_STRATEGY: Sig = java::object_newtype!(Con);
Sig::new().returning(Sig::class(java::util::Optional::<GlobalRef>::PATH)); impl java::Class for Con {
pub const UNACKED_RETRY_STRATEGY: Sig = const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Con");
Sig::new().returning(Sig::class(java::util::Optional::<GlobalRef>::PATH)); }
pub const MAX_ATTEMPTS: Sig =
Sig::new().returning(Sig::class(java::util::Optional::<jint>::PATH));
pub fn acked_retry_strategy(&self, e: &mut JNIEnv<'a>) -> Option<Strategy> { impl Con {
let o = e.call_method(&self.0, pub fn acked_retry_strategy(&self, e: &mut java::Env) -> Option<Strategy> {
"ackedRetryStrategy", static ACKED_RETRY_STRATEGY: java::Method<Con, fn() -> java::util::Optional<RetryStrategy>> =
Self::ACKED_RETRY_STRATEGY, java::Method::new("ackedRetryStrategy");
&[]) ACKED_RETRY_STRATEGY.invoke(e, self)
.unwrap() .to_option(e)
.l() .map(|s| s.to_toad(e))
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<GlobalRef>::from_java(g).to_option(e)
.map(RetryStrategy::from_java)
.map(|j| j.to_toad(e))
} }
pub fn unacked_retry_strategy(&self, e: &mut JNIEnv<'a>) -> Option<Strategy> { pub fn unacked_retry_strategy(&self, e: &mut java::Env) -> Option<Strategy> {
let o = e.call_method(&self.0, static UNACKED_RETRY_STRATEGY: java::Method<Con, fn() -> java::util::Optional<RetryStrategy>> =
"unackedRetryStrategy", java::Method::new("unackedRetryStrategy");
Self::UNACKED_RETRY_STRATEGY, UNACKED_RETRY_STRATEGY.invoke(e, self)
&[]) .to_option(e)
.unwrap() .map(|s| s.to_toad(e))
.l()
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<GlobalRef>::from_java(g).to_option(e)
.map(RetryStrategy::from_java)
.map(|j| j.to_toad(e))
} }
pub fn max_attempts(&self, e: &mut JNIEnv<'a>) -> Option<jint> { pub fn max_attempts(&self, e: &mut java::Env) -> Option<i32> {
let o = e.call_method(&self.0, "maxAttempts", Self::MAX_ATTEMPTS, &[]) static MAX_ATTEMPTS: java::Method<Con, fn() -> java::util::Optional<i32>> =
.unwrap() java::Method::new("maxAttempts");
.l() MAX_ATTEMPTS.invoke(e, self).to_option(e)
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<GlobalRef>::from_java(g).to_option(e)
.map(java::lang::Integer::from_java)
.map(Primitive::dewrap)
} }
} }
pub struct Non<'a>(JObject<'a>); pub struct Non(java::lang::Object);
impl<'a> Non<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Non");
pub const RETRY_STRATEGY: Sig = java::object_newtype!(Non);
Sig::new().returning(Sig::class(java::util::Optional::<GlobalRef>::PATH)); impl java::Class for Non {
pub const MAX_ATTEMPTS: Sig = const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Non");
Sig::new().returning(Sig::class(java::util::Optional::<jint>::PATH)); }
pub fn retry_strategy(&self, e: &mut JNIEnv<'a>) -> Option<Strategy> { impl Non {
let o = e.call_method(&self.0, "retryStrategy", Self::RETRY_STRATEGY, &[]) pub fn retry_strategy(&self, e: &mut java::Env) -> Option<Strategy> {
.unwrap() static RETRY_STRATEGY: java::Method<Non, fn() -> java::util::Optional<RetryStrategy>> =
.l() java::Method::new("retryStrategy");
.unwrap(); RETRY_STRATEGY.invoke(e, self)
let g = e.new_global_ref(o).unwrap(); .to_option(e)
java::util::Optional::<GlobalRef>::from_java(g).to_option(e) .map(|s| s.to_toad(e))
.map(RetryStrategy::from_java)
.map(|j| j.to_toad(e))
} }
pub fn max_attempts(&self, e: &mut JNIEnv<'a>) -> Option<jint> { pub fn max_attempts(&self, e: &mut java::Env) -> Option<i32> {
let o = e.call_method(&self.0, "maxAttempts", Self::MAX_ATTEMPTS, &[]) static MAX_ATTEMPTS: java::Method<Non, fn() -> java::util::Optional<i32>> =
.unwrap() java::Method::new("maxAttempts");
.l() MAX_ATTEMPTS.invoke(e, self).to_option(e)
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<GlobalRef>::from_java(g).to_option(e)
.map(java::lang::Integer::from_java)
.map(Primitive::dewrap)
} }
} }

View File

@ -1,139 +1,86 @@
use core::primitive as rust; use core::primitive as rust;
use jni::objects::{GlobalRef, JByteArray, JObject}; use toad_jni::java;
use jni::JNIEnv;
use toad_jni::cls::java;
use toad_jni::convert::Object;
use toad_jni::Sig;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct u64(GlobalRef); pub struct u64(java::lang::Object);
java::object_newtype!(u64);
impl java::Class for u64 {
const PATH: &'static str = package!(dev.toad.ffi.u64);
}
impl u64 { impl u64 {
pub const PATH: &'static str = package!(dev.toad.ffi.u64); pub fn to_rust(&self, e: &mut java::Env) -> rust::u64 {
pub const CTOR: Sig = Sig::new().arg(Sig::class(java::math::BigInteger::PATH)) static BIGINT_VALUE: java::Method<u64, fn() -> java::math::BigInteger> =
.returning(Sig::VOID); java::Method::new("bigintValue");
pub const BIGINT_VALUE: Sig = Sig::new().returning(Sig::class(java::math::BigInteger::PATH)); let bigint = BIGINT_VALUE.invoke(e, self);
bigint.to_i128(e) as rust::u64
pub fn to_rust<'a>(&self, e: &mut JNIEnv<'a>) -> rust::u64 {
let bi = e.call_method(self.0.as_obj(), "bigintValue", Self::BIGINT_VALUE, &[])
.unwrap()
.l()
.unwrap();
let bi = e.new_global_ref(bi).unwrap();
let bi = java::math::BigInteger::from_java(bi);
bi.to_i128(e) as rust::u64
} }
pub fn from_rust<'a>(e: &mut JNIEnv<'a>, u: rust::u64) -> Self { pub fn from_rust(e: &mut java::Env, u: rust::u64) -> Self {
static CTOR: java::Constructor<u64, fn(java::math::BigInteger)> = java::Constructor::new();
let bi = java::math::BigInteger::from_be_bytes(e, &i128::from(u).to_be_bytes()); let bi = java::math::BigInteger::from_be_bytes(e, &i128::from(u).to_be_bytes());
let bi = e.new_object(Self::PATH, Self::CTOR, &[bi.to_java().as_obj().into()]) CTOR.invoke(e, bi)
.unwrap();
Self(e.new_global_ref(bi).unwrap())
}
}
impl Object for u64 {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
} }
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct u32(GlobalRef); pub struct u32(java::lang::Object);
java::object_newtype!(u32);
impl java::Class for u32 {
const PATH: &'static str = package!(dev.toad.ffi.u32);
}
impl u32 { impl u32 {
pub const PATH: &'static str = package!(dev.toad.ffi.u32); pub fn to_rust(&self, e: &mut java::Env) -> rust::u32 {
pub const CTOR: Sig = Sig::new().arg(Sig::LONG).returning(Sig::VOID); static LONG_VALUE: java::Method<u32, fn() -> i64> = java::Method::new("longValue");
pub const LONG_VALUE: Sig = Sig::new().returning(Sig::LONG); LONG_VALUE.invoke(e, self) as rust::u32
pub fn to_rust<'a>(&self, e: &mut JNIEnv<'a>) -> rust::u32 {
let long = e.call_method(self.0.as_obj(), "longValue", Self::LONG_VALUE, &[])
.unwrap()
.j()
.unwrap();
long as rust::u32
} }
pub fn from_rust<'a>(e: &mut JNIEnv<'a>, u: rust::u32) -> Self { pub fn from_rust(e: &mut java::Env, u: rust::u32) -> Self {
let bi = e.new_object(Self::PATH, Self::CTOR, &[rust::i64::from(u).into()]) static CTOR: java::Constructor<u32, fn(i64)> = java::Constructor::new();
.unwrap(); CTOR.invoke(e, u.into())
Self(e.new_global_ref(bi).unwrap())
}
}
impl Object for u32 {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
} }
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct u16(GlobalRef); pub struct u16(java::lang::Object);
java::object_newtype!(u16);
impl java::Class for u16 {
const PATH: &'static str = package!(dev.toad.ffi.u16);
}
impl u16 { impl u16 {
pub const PATH: &'static str = package!(dev.toad.ffi.u16); pub fn to_rust(&self, e: &mut java::Env) -> rust::u16 {
pub const CTOR: Sig = Sig::new().arg(Sig::INT).returning(Sig::VOID); static INT_VALUE: java::Method<u16, fn() -> i32> = java::Method::new("intValue");
pub const INT_VALUE: Sig = Sig::new().returning(Sig::INT); INT_VALUE.invoke(e, self) as rust::u16
pub fn to_rust<'a>(&self, e: &mut JNIEnv<'a>) -> rust::u16 {
let int = e.call_method(self.0.as_obj(), "intValue", Self::INT_VALUE, &[])
.unwrap()
.i()
.unwrap();
int as rust::u16
} }
pub fn from_rust<'a>(e: &mut JNIEnv<'a>, u: rust::u16) -> Self { pub fn from_rust(e: &mut java::Env, u: rust::u16) -> Self {
let bi = e.new_object(Self::PATH, Self::CTOR, &[rust::i32::from(u).into()]) static CTOR: java::Constructor<u16, fn(i32)> = java::Constructor::new();
.unwrap(); CTOR.invoke(e, u.into())
Self(e.new_global_ref(bi).unwrap())
}
}
impl Object for u16 {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
} }
} }
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct u8(GlobalRef); pub struct u8(java::lang::Object);
java::object_newtype!(u8);
impl java::Class for u8 {
const PATH: &'static str = package!(dev.toad.ffi.u8);
}
impl u8 { impl u8 {
pub const PATH: &'static str = package!(dev.toad.ffi.u8); pub fn to_rust(&self, e: &mut java::Env) -> rust::u8 {
pub const CTOR: Sig = Sig::new().arg(Sig::SHORT).returning(Sig::VOID); static SHORT_VALUE: java::Method<u8, fn() -> i16> = java::Method::new("shortValue");
pub const SHORT_VALUE: Sig = Sig::new().returning(Sig::SHORT); SHORT_VALUE.invoke(e, self) as rust::u8
pub fn to_rust<'a>(&self, e: &mut JNIEnv<'a>) -> rust::u8 {
let int = e.call_method(self.0.as_obj(), "shortValue", Self::SHORT_VALUE, &[])
.unwrap()
.s()
.unwrap();
int as rust::u8
} }
pub fn from_rust<'a>(e: &mut JNIEnv<'a>, u: rust::u8) -> Self { pub fn from_rust(e: &mut java::Env, u: rust::u8) -> Self {
let bi = e.new_object(Self::PATH, Self::CTOR, &[rust::i16::from(u).into()]) static CTOR: java::Constructor<u8, fn(i16)> = java::Constructor::new();
.unwrap(); CTOR.invoke(e, u.into())
Self(e.new_global_ref(bi).unwrap())
}
}
impl Object for u8 {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
} }
} }

View File

@ -1,8 +1,16 @@
package dev.toad; package dev.toad;
import dev.toad.msg.MessageRef;
import java.util.Optional;
public class Runtime { public class Runtime {
public static native void init(RuntimeOptions o); private final long addr;
private Runtime() {} private static native long init(RuntimeOptions o);
private native Optional<MessageRef> pollReq(RuntimeOptions o);
public Runtime(RuntimeOptions o) {
this.addr = Runtime.init(o);
}
} }