refactor: rework msg module structure
This commit is contained in:
parent
913ed46e13
commit
8679ae0a78
@ -29,7 +29,7 @@ lazy val root = project
|
||||
Compile / doc / javacOptions ++= Seq(
|
||||
"--enable-preview",
|
||||
"--release",
|
||||
"20",
|
||||
"20"
|
||||
),
|
||||
Compile / compile / javacOptions ++= Seq(
|
||||
"--enable-preview",
|
||||
|
1
glue/src/dev/mod.rs
Normal file
1
glue/src/dev/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod toad;
|
2
glue/src/dev/toad/ffi/mod.rs
Normal file
2
glue/src/dev/toad/ffi/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
mod uint;
|
||||
pub use uint::{u16, u32, u64, u8};
|
@ -1,42 +1,95 @@
|
||||
pub mod ffi;
|
||||
pub mod msg;
|
||||
|
||||
mod retry_strategy;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use jni::objects::JClass;
|
||||
use jni::objects::{JClass, JObject};
|
||||
use jni::sys::jobject;
|
||||
use toad::config::{self, BytesPerSecond, Config};
|
||||
pub use retry_strategy::RetryStrategy;
|
||||
use toad::platform::Platform;
|
||||
use toad::retry::{Attempts, Strategy};
|
||||
use toad::time::Millis;
|
||||
use toad_jni::java::{self, Class, Object};
|
||||
use toad_jni::java::{self, Object};
|
||||
|
||||
use crate::retry_strategy::RetryStrategy;
|
||||
use crate::uint;
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
use crate::Runtime;
|
||||
|
||||
pub struct RuntimeConfig(java::lang::Object);
|
||||
pub struct Toad(java::lang::Object);
|
||||
|
||||
java::object_newtype!(RuntimeConfig);
|
||||
impl java::Class for RuntimeConfig {
|
||||
const PATH: &'static str = concat!(package!(dev.toad.ToadRuntime), "$Config");
|
||||
impl Toad {
|
||||
pub fn new(e: &mut java::Env, cfg: Config) -> Self {
|
||||
static CTOR: java::Constructor<Toad, fn(Config)> = java::Constructor::new();
|
||||
CTOR.invoke(e, cfg)
|
||||
}
|
||||
|
||||
pub fn poll_req(&self, e: &mut java::Env) -> Option<msg::ref_::Message> {
|
||||
static POLL_REQ: java::Method<Toad, fn() -> java::util::Optional<msg::ref_::Message>> =
|
||||
java::Method::new("pollReq");
|
||||
POLL_REQ.invoke(e, self).to_option(e)
|
||||
}
|
||||
|
||||
pub fn config(&self, e: &mut java::Env) -> Config {
|
||||
static CONFIG: java::Method<Toad, fn() -> Config> = java::Method::new("config");
|
||||
CONFIG.invoke(e, self)
|
||||
}
|
||||
|
||||
fn init_impl(e: &mut java::Env, cfg: Config) -> i64 {
|
||||
let r = || Runtime::try_new(cfg.addr(e), cfg.to_toad(e)).unwrap();
|
||||
unsafe { crate::mem::Shared::init(r).addr() as i64 }
|
||||
}
|
||||
|
||||
fn poll_req_impl(e: &mut java::Env, addr: i64) -> java::util::Optional<msg::ref_::Message> {
|
||||
match unsafe {
|
||||
Shared::deref::<Runtime>(/* TODO */ 0, addr).as_ref()
|
||||
.unwrap()
|
||||
}.poll_req()
|
||||
{
|
||||
| Ok(req) => {
|
||||
let mr = msg::ref_::Message::new(e, req.unwrap().into());
|
||||
java::util::Optional::<msg::ref_::Message>::of(e, mr)
|
||||
},
|
||||
| Err(nb::Error::WouldBlock) => java::util::Optional::<msg::ref_::Message>::empty(e),
|
||||
| Err(nb::Error::Other(err)) => {
|
||||
e.throw(format!("{:?}", err)).unwrap();
|
||||
java::util::Optional::<msg::ref_::Message>::empty(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimeConfig {
|
||||
java::object_newtype!(Toad);
|
||||
|
||||
impl java::Class for Toad {
|
||||
const PATH: &'static str = package!(dev.toad.Toad);
|
||||
}
|
||||
|
||||
pub struct Config(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Config);
|
||||
impl java::Class for Config {
|
||||
const PATH: &'static str = concat!(package!(dev.toad.Toad), "$Config");
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn addr(&self, e: &mut java::Env) -> SocketAddr {
|
||||
static ADDRESS: java::Field<RuntimeConfig, java::net::InetSocketAddress> =
|
||||
java::Field::new("addr");
|
||||
static ADDRESS: java::Field<Config, java::net::InetSocketAddress> = java::Field::new("addr");
|
||||
ADDRESS.get(e, self).to_std(e)
|
||||
}
|
||||
|
||||
pub fn concurrency(&self, e: &mut java::Env) -> u8 {
|
||||
static RUNTIME_CONFIG_CONCURRENCY: java::Field<RuntimeConfig, uint::u8> =
|
||||
static RUNTIME_CONFIG_CONCURRENCY: java::Field<Config, ffi::u8> =
|
||||
java::Field::new("concurrency");
|
||||
RUNTIME_CONFIG_CONCURRENCY.get(e, self).to_rust(e)
|
||||
}
|
||||
|
||||
pub fn msg(&self, e: &mut java::Env) -> Msg {
|
||||
static RUNTIME_CONFIG_MSG: java::Method<RuntimeConfig, fn() -> Msg> = java::Method::new("msg");
|
||||
static RUNTIME_CONFIG_MSG: java::Method<Config, fn() -> Msg> = java::Method::new("msg");
|
||||
RUNTIME_CONFIG_MSG.invoke(e, self)
|
||||
}
|
||||
|
||||
pub fn new(e: &mut java::Env, c: Config, addr: SocketAddr) -> Self {
|
||||
static CTOR: java::Constructor<RuntimeConfig, fn(java::net::InetSocketAddress, uint::u8, Msg)> =
|
||||
pub fn new(e: &mut java::Env, c: toad::config::Config, addr: SocketAddr) -> Self {
|
||||
static CTOR: java::Constructor<Config, fn(java::net::InetSocketAddress, ffi::u8, Msg)> =
|
||||
java::Constructor::new();
|
||||
|
||||
let con = Con::new(e,
|
||||
@ -51,7 +104,7 @@ impl RuntimeConfig {
|
||||
con,
|
||||
non);
|
||||
|
||||
let concurrency = uint::u8::from_rust(e, c.max_concurrent_requests);
|
||||
let concurrency = ffi::u8::from_rust(e, c.max_concurrent_requests);
|
||||
|
||||
let address = java::net::InetSocketAddress::from_std(e, addr);
|
||||
|
||||
@ -59,23 +112,23 @@ impl RuntimeConfig {
|
||||
jcfg
|
||||
}
|
||||
|
||||
pub fn to_toad(&self, e: &mut java::Env) -> config::Config {
|
||||
pub fn to_toad(&self, e: &mut java::Env) -> toad::config::Config {
|
||||
let msg = self.msg(e);
|
||||
let con = msg.con(e);
|
||||
let non = msg.non(e);
|
||||
|
||||
config::Config { max_concurrent_requests: self.concurrency(e) as u8,
|
||||
msg: config::Msg { token_seed: msg.token_seed(e) as _,
|
||||
probing_rate: BytesPerSecond(msg.probing_rate(e) as _),
|
||||
toad::config::Config { max_concurrent_requests: self.concurrency(e) as u8,
|
||||
msg: toad::config::Msg { token_seed: msg.token_seed(e) as _,
|
||||
probing_rate: toad::config::BytesPerSecond(msg.probing_rate(e) as _),
|
||||
multicast_response_leisure:
|
||||
msg.multicast_response_leisure(e),
|
||||
con: config::Con { unacked_retry_strategy:
|
||||
con: toad::config::Con { unacked_retry_strategy:
|
||||
con.unacked_retry_strategy(e),
|
||||
acked_retry_strategy:
|
||||
con.acked_retry_strategy(e),
|
||||
max_attempts:
|
||||
Attempts(con.max_attempts(e) as _) },
|
||||
non: config::Non { retry_strategy:
|
||||
non: toad::config::Non { retry_strategy:
|
||||
non.retry_strategy(e),
|
||||
max_attempts:
|
||||
Attempts(non.max_attempts(e) as _) } } }
|
||||
@ -87,7 +140,7 @@ pub struct Msg(java::lang::Object);
|
||||
java::object_newtype!(Msg);
|
||||
|
||||
impl java::Class for Msg {
|
||||
const PATH: &'static str = concat!(package!(dev.toad.ToadRuntime), "$Config$Msg");
|
||||
const PATH: &'static str = concat!(package!(dev.toad.Toad), "$Config$Msg");
|
||||
}
|
||||
|
||||
impl Msg {
|
||||
@ -98,10 +151,10 @@ impl Msg {
|
||||
con: Con,
|
||||
non: Non)
|
||||
-> Self {
|
||||
static CTOR: java::Constructor<Msg, fn(uint::u16, uint::u16, java::time::Duration, Con, Non)> =
|
||||
static CTOR: java::Constructor<Msg, fn(ffi::u16, ffi::u16, java::time::Duration, Con, Non)> =
|
||||
java::Constructor::new();
|
||||
let token_seed = uint::u16::from_rust(e, token_seed);
|
||||
let probe_rate = uint::u16::from_rust(e, probe_rate);
|
||||
let token_seed = ffi::u16::from_rust(e, token_seed);
|
||||
let probe_rate = ffi::u16::from_rust(e, probe_rate);
|
||||
let multicast_response_leisure =
|
||||
java::time::Duration::of_millis(e, multicast_response_leisure.0 as i64);
|
||||
|
||||
@ -147,20 +200,20 @@ pub struct Con(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Con);
|
||||
impl java::Class for Con {
|
||||
const PATH: &'static str = concat!(package!(dev.toad.ToadRuntime), "$Config$Msg$Con");
|
||||
const PATH: &'static str = concat!(package!(dev.toad.Toad), "$Config$Msg$Con");
|
||||
}
|
||||
|
||||
impl Con {
|
||||
pub fn new(e: &mut java::Env,
|
||||
unacked: toad::retry::Strategy,
|
||||
acked: toad::retry::Strategy,
|
||||
unacked: Strategy,
|
||||
acked: Strategy,
|
||||
max_attempts: Attempts)
|
||||
-> Self {
|
||||
static CTOR: java::Constructor<Con, fn(RetryStrategy, RetryStrategy, uint::u16)> =
|
||||
static CTOR: java::Constructor<Con, fn(RetryStrategy, RetryStrategy, ffi::u16)> =
|
||||
java::Constructor::new();
|
||||
let unacked = RetryStrategy::from_toad(e, unacked);
|
||||
let acked = RetryStrategy::from_toad(e, acked);
|
||||
let att = uint::u16::from_rust(e, max_attempts.0);
|
||||
let att = ffi::u16::from_rust(e, max_attempts.0);
|
||||
CTOR.invoke(e, unacked, acked, att)
|
||||
}
|
||||
|
||||
@ -186,14 +239,14 @@ pub struct Non(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Non);
|
||||
impl java::Class for Non {
|
||||
const PATH: &'static str = concat!(package!(dev.toad.ToadRuntime), "$Config$Msg$Non");
|
||||
const PATH: &'static str = concat!(package!(dev.toad.Toad), "$Config$Msg$Non");
|
||||
}
|
||||
|
||||
impl Non {
|
||||
pub fn new(e: &mut java::Env, strat: toad::retry::Strategy, max_attempts: Attempts) -> Self {
|
||||
static CTOR: java::Constructor<Non, fn(RetryStrategy, uint::u16)> = java::Constructor::new();
|
||||
pub fn new(e: &mut java::Env, strat: Strategy, max_attempts: Attempts) -> Self {
|
||||
static CTOR: java::Constructor<Non, fn(RetryStrategy, ffi::u16)> = java::Constructor::new();
|
||||
let strat = RetryStrategy::from_toad(e, strat);
|
||||
let att = uint::u16::from_rust(e, max_attempts.0);
|
||||
let att = ffi::u16::from_rust(e, max_attempts.0);
|
||||
CTOR.invoke(e, strat, att)
|
||||
}
|
||||
|
||||
@ -210,10 +263,30 @@ impl Non {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_Runtime_defaultConfigImpl<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>)
|
||||
-> jobject {
|
||||
RuntimeConfig::new(&mut env,
|
||||
Config::default(),
|
||||
SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5683)).yield_to_java(&mut env)
|
||||
pub extern "system" fn Java_dev_toad_Toad_defaultConfigImpl<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>)
|
||||
-> jobject {
|
||||
Config::new(&mut env,
|
||||
toad::config::Config::default(),
|
||||
SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5683)).yield_to_java(&mut env)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_Toad_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::<Config>(e);
|
||||
|
||||
Toad::init_impl(e, cfg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_Toad_pollReq<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let e = &mut e;
|
||||
Toad::poll_req_impl(e, addr).yield_to_java(e)
|
||||
}
|
15
glue/src/dev/toad/msg/code.rs
Normal file
15
glue/src/dev/toad/msg/code.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use toad_jni::java;
|
||||
|
||||
pub struct Code(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Code);
|
||||
impl java::Class for Code {
|
||||
const PATH: &'static str = package!(dev.toad.msg.Code);
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn new(e: &mut java::Env, code: toad_msg::Code) -> Self {
|
||||
static CTOR: java::Constructor<Code, fn(i32, i32)> = java::Constructor::new();
|
||||
CTOR.invoke(e, code.class.into(), code.detail.into())
|
||||
}
|
||||
}
|
7
glue/src/dev/toad/msg/mod.rs
Normal file
7
glue/src/dev/toad/msg/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
pub mod ref_;
|
||||
|
||||
mod ty;
|
||||
pub use ty::Type;
|
||||
|
||||
mod code;
|
||||
pub use code::Code;
|
8
glue/src/dev/toad/msg/ref_/mod.rs
Normal file
8
glue/src/dev/toad/msg/ref_/mod.rs
Normal file
@ -0,0 +1,8 @@
|
||||
mod opt;
|
||||
pub use opt::Opt;
|
||||
|
||||
mod msg;
|
||||
pub use msg::Message;
|
||||
|
||||
mod opt_value;
|
||||
pub use opt_value::OptValue;
|
97
glue/src/dev/toad/msg/ref_/msg.rs
Normal file
97
glue/src/dev/toad/msg/ref_/msg.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use jni::objects::JClass;
|
||||
use jni::sys::jobject;
|
||||
use toad_jni::java::{self, Object};
|
||||
|
||||
use crate::dev::toad::msg::ref_::Opt;
|
||||
use crate::dev::toad::msg::{Code, Type};
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
|
||||
pub struct Message(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Message);
|
||||
impl java::Class for Message {
|
||||
const PATH: &'static str = package!(dev.toad.msg.ref.Message);
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(env: &mut java::Env, message: toad_msg::alloc::Message) -> Self {
|
||||
let ptr = unsafe { Shared::alloc_message(message) };
|
||||
static CTOR: java::Constructor<Message, fn(i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, ptr.addr() as i64)
|
||||
}
|
||||
|
||||
pub fn close(&self, env: &mut java::Env) {
|
||||
static CLOSE: java::Method<Message, fn()> = java::Method::new("close");
|
||||
CLOSE.invoke(env, self)
|
||||
}
|
||||
|
||||
pub fn ty(&self, env: &mut java::Env) -> toad_msg::Type {
|
||||
static TYPE: java::Method<Message, fn() -> Type> = java::Method::new("type");
|
||||
TYPE.invoke(env, self).to_toad(env)
|
||||
}
|
||||
|
||||
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut toad_msg::alloc::Message {
|
||||
crate::mem::Shared::deref::<toad_msg::alloc::Message>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_id<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> i32 {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
msg.id.0 as i32
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_token<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
env.byte_array_from_slice(&msg.token.0).unwrap().as_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_payload<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
env.byte_array_from_slice(&msg.payload.0).unwrap().as_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_type<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
Type::new(&mut e, msg.ty).yield_to_java(&mut e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_code<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
Code::new(&mut e, msg.code).yield_to_java(&mut e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_opts<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { Message::ptr(addr) };
|
||||
let opts = &msg.opts;
|
||||
|
||||
let refs = opts.into_iter()
|
||||
.map(|(n, v)| Opt::new(&mut e, v as *const _ as i64, n.0.into()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
refs.yield_to_java(&mut e)
|
||||
}
|
57
glue/src/dev/toad/msg/ref_/opt.rs
Normal file
57
glue/src/dev/toad/msg/ref_/opt.rs
Normal file
@ -0,0 +1,57 @@
|
||||
use jni::objects::{JClass, JObject};
|
||||
use jni::sys::jobject;
|
||||
use jni::JNIEnv;
|
||||
use toad_jni::java::{self, Object};
|
||||
use toad_msg::OptNumber;
|
||||
|
||||
use super::OptValue;
|
||||
use crate::mem::SharedMemoryRegion;
|
||||
|
||||
pub struct Opt(pub java::lang::Object);
|
||||
|
||||
java::object_newtype!(Opt);
|
||||
|
||||
impl java::Class for Opt {
|
||||
const PATH: &'static str = package!(dev.toad.msg.ref.Option);
|
||||
}
|
||||
|
||||
impl Opt {
|
||||
pub fn new(env: &mut java::Env, addr: i64, num: i64) -> Self {
|
||||
static CTOR: java::Constructor<Opt, fn(i64, i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, addr, num)
|
||||
}
|
||||
|
||||
pub fn number(&self, env: &mut java::Env) -> OptNumber {
|
||||
static NUMBER: java::Field<Opt, i64> = java::Field::new("number");
|
||||
OptNumber(NUMBER.get(env, self) as u32)
|
||||
}
|
||||
|
||||
pub unsafe fn values_ptr<'a>(addr: i64) -> &'a mut Vec<toad_msg::OptValue<Vec<u8>>> {
|
||||
crate::mem::Shared::deref::<Vec<toad_msg::OptValue<Vec<u8>>>>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_Option_number<'local>(mut env: JNIEnv<'local>,
|
||||
o: JObject<'local>,
|
||||
p: i64)
|
||||
-> i64 {
|
||||
java::lang::Object::from_local(&mut env, o).upcast_to::<Opt>(&mut env)
|
||||
.number(&mut env)
|
||||
.0 as i64
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_Option_values<'local>(mut e: JNIEnv<'local>,
|
||||
_: JClass<'local>,
|
||||
p: i64)
|
||||
-> jobject {
|
||||
let o = &unsafe { Opt::values_ptr(p) };
|
||||
|
||||
let refs = o.iter()
|
||||
.map(|v| OptValue::new(&mut e, (&v.0 as *const Vec<u8>).addr() as i64))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
refs.yield_to_java(&mut e)
|
||||
}
|
33
glue/src/dev/toad/msg/ref_/opt_value.rs
Normal file
33
glue/src/dev/toad/msg/ref_/opt_value.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use jni::objects::JClass;
|
||||
use jni::sys::jobject;
|
||||
use toad_jni::java;
|
||||
|
||||
use crate::mem::SharedMemoryRegion;
|
||||
|
||||
pub struct OptValue(java::lang::Object);
|
||||
|
||||
java::object_newtype!(OptValue);
|
||||
impl java::Class for OptValue {
|
||||
const PATH: &'static str = package!(dev.toad.msg.ref.OptionValue);
|
||||
}
|
||||
|
||||
impl OptValue {
|
||||
pub fn new(env: &mut java::Env, addr: i64) -> Self {
|
||||
static CTOR: java::Constructor<OptValue, fn(i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, addr)
|
||||
}
|
||||
|
||||
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut toad_msg::OptValue<Vec<u8>> {
|
||||
crate::mem::Shared::deref::<toad_msg::OptValue<Vec<u8>>>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_OptionValue_bytes<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
p: i64)
|
||||
-> jobject {
|
||||
let val = unsafe { OptValue::ptr(p) };
|
||||
env.byte_array_from_slice(val.as_bytes()).unwrap().as_raw()
|
||||
}
|
36
glue/src/dev/toad/msg/ty.rs
Normal file
36
glue/src/dev/toad/msg/ty.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use toad_jni::java;
|
||||
|
||||
pub struct Type(java::lang::Object);
|
||||
|
||||
java::object_newtype!(Type);
|
||||
impl java::Class for Type {
|
||||
const PATH: &'static str = package!(dev.toad.msg.Type);
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn new(env: &mut java::Env, ty: toad_msg::Type) -> Self {
|
||||
static FROM_STRING: java::StaticMethod<Type, fn(String) -> Type> =
|
||||
java::StaticMethod::new("fromString");
|
||||
|
||||
let str = match ty {
|
||||
| toad_msg::Type::Con => "CON",
|
||||
| toad_msg::Type::Non => "NON",
|
||||
| toad_msg::Type::Ack => "ACK",
|
||||
| toad_msg::Type::Reset => "RESET",
|
||||
};
|
||||
|
||||
FROM_STRING.invoke(env, str.to_string())
|
||||
}
|
||||
|
||||
pub fn to_toad(&self, env: &mut java::Env) -> toad_msg::Type {
|
||||
static TO_STRING: java::Method<Type, fn() -> String> = java::Method::new("toString");
|
||||
|
||||
match TO_STRING.invoke(env, self).trim().to_uppercase().as_str() {
|
||||
| "CON" => toad_msg::Type::Con,
|
||||
| "NON" => toad_msg::Type::Non,
|
||||
| "ACK" => toad_msg::Type::Ack,
|
||||
| "RESET" => toad_msg::Type::Reset,
|
||||
| o => panic!("malformed message type {}", o),
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@ use toad::retry::Strategy;
|
||||
use toad::time::Millis;
|
||||
use toad_jni::java::{self, Object};
|
||||
|
||||
use crate::uint;
|
||||
use crate::dev::toad::ffi;
|
||||
|
||||
pub struct RetryStrategyExp(java::lang::Object);
|
||||
|
||||
@ -26,12 +26,12 @@ impl RetryStrategyExp {
|
||||
}
|
||||
|
||||
pub fn init_min(&self, e: &mut java::Env) -> Millis {
|
||||
static INIT_MIN: java::Field<RetryStrategyExp, uint::u64> = java::Field::new("initMin");
|
||||
static INIT_MIN: java::Field<RetryStrategyExp, ffi::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");
|
||||
static INIT_MAX: java::Field<RetryStrategyExp, ffi::u64> = java::Field::new("initMax");
|
||||
Millis::new(INIT_MAX.get(e, self).to_rust(e))
|
||||
}
|
||||
}
|
||||
@ -58,12 +58,12 @@ impl RetryStrategyDelay {
|
||||
}
|
||||
|
||||
pub fn min(&self, e: &mut java::Env) -> Millis {
|
||||
static MIN: java::Field<RetryStrategyDelay, uint::u64> = java::Field::new("min");
|
||||
static MIN: java::Field<RetryStrategyDelay, ffi::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");
|
||||
static MAX: java::Field<RetryStrategyDelay, ffi::u64> = java::Field::new("max");
|
||||
Millis::new(MAX.get(e, self).to_rust(e))
|
||||
}
|
||||
}
|
@ -6,13 +6,11 @@ use toad_jni::java::{self, Object, Signature};
|
||||
use toad_msg::alloc::Message;
|
||||
use toad_msg::{Code, Id, Token, Type};
|
||||
|
||||
use crate::message_type::MessageType;
|
||||
use crate::runtime::Runtime;
|
||||
use crate::runtime_config::RuntimeConfig;
|
||||
use crate::{dev, Runtime};
|
||||
|
||||
#[non_exhaustive]
|
||||
struct State {
|
||||
pub runtime: Runtime,
|
||||
pub runtime: dev::toad::Toad,
|
||||
pub env: java::Env<'static>,
|
||||
pub client: crate::Runtime,
|
||||
pub srv_addr: SocketAddr,
|
||||
@ -22,12 +20,12 @@ fn init() -> State {
|
||||
let mut _env = crate::test::init();
|
||||
let env = &mut _env;
|
||||
|
||||
let cfg = RuntimeConfig::new(env,
|
||||
Config::default(),
|
||||
std::net::SocketAddr::new(std::net::Ipv4Addr::UNSPECIFIED.into(),
|
||||
5683));
|
||||
let runtime = Runtime::new(env, cfg);
|
||||
let client = crate::Runtime::try_new("0.0.0.0:5684", Default::default()).unwrap();
|
||||
let cfg =
|
||||
dev::toad::Config::new(env,
|
||||
Config::default(),
|
||||
std::net::SocketAddr::new(std::net::Ipv4Addr::UNSPECIFIED.into(), 5683));
|
||||
let runtime = dev::toad::Toad::new(env, cfg);
|
||||
let client = Runtime::try_new("0.0.0.0:5684", Default::default()).unwrap();
|
||||
|
||||
State { runtime,
|
||||
env: _env,
|
||||
@ -60,7 +58,7 @@ fn message_ref_should_throw_when_used_after_close(State {runtime, env, client, s
|
||||
let req_o = req.downcast(env);
|
||||
env.call_method(req_o.as_local(),
|
||||
"type",
|
||||
Signature::of::<fn() -> MessageType>(),
|
||||
Signature::of::<fn() -> dev::toad::msg::Type>(),
|
||||
&[])
|
||||
.ok();
|
||||
|
||||
|
@ -5,8 +5,8 @@ use std::ffi::c_void;
|
||||
use jni::JavaVM;
|
||||
use mem::SharedMemoryRegion;
|
||||
|
||||
pub type Runtime =
|
||||
toad::std::Platform<toad::std::dtls::N, toad::step::runtime::std::Runtime<toad::std::dtls::N>>;
|
||||
pub type Runtime = ::toad::std::Platform<::toad::std::dtls::N,
|
||||
::toad::step::runtime::std::Runtime<::toad::std::dtls::N>>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! package {
|
||||
@ -15,16 +15,8 @@ macro_rules! package {
|
||||
(ext $start:ident.$($thing:ident).+) => {concat!(stringify!($start), $("/", stringify!($thing)),+)};
|
||||
}
|
||||
|
||||
pub mod dev;
|
||||
pub mod mem;
|
||||
pub mod message_code;
|
||||
pub mod message_opt_ref;
|
||||
pub mod message_opt_value_ref;
|
||||
pub mod message_ref;
|
||||
pub mod message_type;
|
||||
pub mod retry_strategy;
|
||||
pub mod runtime;
|
||||
pub mod runtime_config;
|
||||
pub mod uint;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn JNI_OnLoad(jvm: JavaVM, _: *const c_void) -> i32 {
|
||||
@ -51,8 +43,7 @@ pub mod test {
|
||||
use toad::time::Millis;
|
||||
use toad_jni::java;
|
||||
|
||||
use crate::retry_strategy::RetryStrategy;
|
||||
use crate::runtime_config::RuntimeConfig;
|
||||
use crate::dev;
|
||||
|
||||
pub fn init<'a>() -> java::Env<'a> {
|
||||
static INIT: Once = Once::new();
|
||||
@ -82,9 +73,9 @@ pub mod test {
|
||||
let mut e = init();
|
||||
let e = &mut e;
|
||||
|
||||
let r = RuntimeConfig::new(e,
|
||||
Config::default(),
|
||||
SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5683));
|
||||
let r = dev::toad::Config::new(e,
|
||||
Config::default(),
|
||||
SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 5683));
|
||||
assert_eq!(r.to_toad(e), Config::default());
|
||||
}
|
||||
|
||||
@ -95,24 +86,23 @@ pub mod test {
|
||||
|
||||
let r = Strategy::Exponential { init_min: Millis::new(0),
|
||||
init_max: Millis::new(100) };
|
||||
assert_eq!(RetryStrategy::from_toad(e, r).to_toad(e), r);
|
||||
assert_eq!(dev::toad::RetryStrategy::from_toad(e, r).to_toad(e), r);
|
||||
|
||||
let r = Strategy::Delay { min: Millis::new(0),
|
||||
max: Millis::new(100) };
|
||||
assert_eq!(RetryStrategy::from_toad(e, r).to_toad(e), r);
|
||||
assert_eq!(dev::toad::RetryStrategy::from_toad(e, r).to_toad(e), r);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uint() {
|
||||
use crate::uint;
|
||||
|
||||
let mut e = init();
|
||||
let e = &mut e;
|
||||
|
||||
macro_rules! case {
|
||||
($u:ident) => {{
|
||||
assert_eq!(uint::$u::from_rust(e, $u::MAX).to_rust(e), $u::MAX);
|
||||
assert_eq!(uint::$u::from_rust(e, 0).to_rust(e), 0);
|
||||
assert_eq!(dev::toad::ffi::$u::from_rust(e, $u::MAX).to_rust(e),
|
||||
$u::MAX);
|
||||
assert_eq!(dev::toad::ffi::$u::from_rust(e, 0).to_rust(e), 0);
|
||||
}};
|
||||
}
|
||||
|
||||
|
@ -1,16 +0,0 @@
|
||||
use toad_jni::java;
|
||||
use toad_msg::Code;
|
||||
|
||||
pub struct MessageCode(java::lang::Object);
|
||||
|
||||
java::object_newtype!(MessageCode);
|
||||
impl java::Class for MessageCode {
|
||||
const PATH: &'static str = package!(dev.toad.msg.MessageCode);
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
use jni::objects::{JClass, JObject};
|
||||
use jni::sys::jobject;
|
||||
use jni::JNIEnv;
|
||||
use toad_jni::java::{self, Object};
|
||||
use toad_msg::{OptNumber, OptValue};
|
||||
|
||||
use crate::mem::SharedMemoryRegion;
|
||||
use crate::message_opt_value_ref::MessageOptValueRef;
|
||||
|
||||
pub struct MessageOptRef(pub java::lang::Object);
|
||||
|
||||
java::object_newtype!(MessageOptRef);
|
||||
|
||||
impl java::Class for MessageOptRef {
|
||||
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 number(&self, env: &mut java::Env) -> OptNumber {
|
||||
static NUMBER: java::Field<MessageOptRef, i64> = java::Field::new("number");
|
||||
OptNumber(NUMBER.get(env, self) as u32)
|
||||
}
|
||||
|
||||
pub unsafe fn values_ptr<'a>(addr: i64) -> &'a mut Vec<OptValue<Vec<u8>>> {
|
||||
crate::mem::Shared::deref::<Vec<OptValue<Vec<u8>>>>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageOptionRef_number<'local>(mut env: JNIEnv<'local>,
|
||||
o: JObject<'local>,
|
||||
p: i64)
|
||||
-> i64 {
|
||||
java::lang::Object::from_local(&mut env, o).upcast_to::<MessageOptRef>(&mut env)
|
||||
.number(&mut env)
|
||||
.0 as i64
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageOptionRef_values<'local>(mut e: JNIEnv<'local>,
|
||||
_: JClass<'local>,
|
||||
p: i64)
|
||||
-> jobject {
|
||||
let o = &unsafe { MessageOptRef::values_ptr(p) };
|
||||
|
||||
let refs = o.iter()
|
||||
.map(|v| MessageOptValueRef::new(&mut e, (&v.0 as *const Vec<u8>).addr() as i64))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
refs.yield_to_java(&mut e)
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
use jni::objects::JClass;
|
||||
use jni::sys::jobject;
|
||||
use toad_jni::java;
|
||||
use toad_msg::OptValue;
|
||||
|
||||
use crate::mem::SharedMemoryRegion;
|
||||
|
||||
pub struct MessageOptValueRef(java::lang::Object);
|
||||
|
||||
java::object_newtype!(MessageOptValueRef);
|
||||
impl java::Class for MessageOptValueRef {
|
||||
const PATH: &'static str = package!(dev.toad.msg.MessageOptionValueRef);
|
||||
}
|
||||
|
||||
impl MessageOptValueRef {
|
||||
pub fn new(env: &mut java::Env, addr: i64) -> Self {
|
||||
static CTOR: java::Constructor<MessageOptValueRef, fn(i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, addr)
|
||||
}
|
||||
|
||||
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut OptValue<Vec<u8>> {
|
||||
crate::mem::Shared::deref::<OptValue<Vec<u8>>>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageOptionValueRef_bytes<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
p: i64)
|
||||
-> jobject {
|
||||
let val = unsafe { MessageOptValueRef::ptr(p) };
|
||||
env.byte_array_from_slice(val.as_bytes()).unwrap().as_raw()
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
use jni::objects::JClass;
|
||||
use jni::sys::jobject;
|
||||
use toad_jni::java::{self, Object};
|
||||
use toad_msg::alloc::Message;
|
||||
use toad_msg::Type;
|
||||
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
use crate::message_code::MessageCode;
|
||||
use crate::message_opt_ref::MessageOptRef;
|
||||
use crate::message_type::MessageType;
|
||||
|
||||
pub struct MessageRef(java::lang::Object);
|
||||
|
||||
java::object_newtype!(MessageRef);
|
||||
impl java::Class for MessageRef {
|
||||
const PATH: &'static str = package!(dev.toad.msg.MessageRef);
|
||||
}
|
||||
|
||||
impl MessageRef {
|
||||
pub fn new(env: &mut java::Env, message: Message) -> Self {
|
||||
let ptr = unsafe { Shared::alloc_message(message) };
|
||||
static CTOR: java::Constructor<MessageRef, fn(i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, ptr.addr() as i64)
|
||||
}
|
||||
|
||||
pub fn close(&self, env: &mut java::Env) {
|
||||
static CLOSE: java::Method<MessageRef, fn()> = java::Method::new("close");
|
||||
CLOSE.invoke(env, self)
|
||||
}
|
||||
|
||||
pub fn ty(&self, env: &mut java::Env) -> Type {
|
||||
static TYPE: java::Method<MessageRef, fn() -> MessageType> = java::Method::new("type");
|
||||
TYPE.invoke(env, self).to_toad(env)
|
||||
}
|
||||
|
||||
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut Message {
|
||||
crate::mem::Shared::deref::<Message>(/* TODO */ 0, addr).as_mut()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_id<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> i32 {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
msg.id.0 as i32
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_token<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
env.byte_array_from_slice(&msg.token.0).unwrap().as_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_payload<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
env.byte_array_from_slice(&msg.payload.0).unwrap().as_raw()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_type<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
MessageType::new(&mut e, msg.ty).yield_to_java(&mut e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_code<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
MessageCode::new(&mut e, msg.code).yield_to_java(&mut e)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_MessageRef_opts<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe { MessageRef::ptr(addr) };
|
||||
let opts = &msg.opts;
|
||||
|
||||
let refs = opts.into_iter()
|
||||
.map(|(n, v)| MessageOptRef::new(&mut e, v as *const _ as i64, n.0.into()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
refs.yield_to_java(&mut e)
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
use toad_jni::java;
|
||||
use toad_msg::Type;
|
||||
|
||||
pub struct MessageType(java::lang::Object);
|
||||
|
||||
java::object_newtype!(MessageType);
|
||||
impl java::Class for MessageType {
|
||||
const PATH: &'static str = package!(dev.toad.msg.MessageType);
|
||||
}
|
||||
|
||||
impl MessageType {
|
||||
pub fn new(env: &mut java::Env, ty: Type) -> Self {
|
||||
static FROM_STRING: java::StaticMethod<MessageType, fn(String) -> MessageType> =
|
||||
java::StaticMethod::new("fromString");
|
||||
|
||||
let str = match ty {
|
||||
| Type::Con => "CON",
|
||||
| Type::Non => "NON",
|
||||
| Type::Ack => "ACK",
|
||||
| Type::Reset => "RESET",
|
||||
};
|
||||
|
||||
FROM_STRING.invoke(env, str.to_string())
|
||||
}
|
||||
|
||||
pub fn to_toad(&self, env: &mut java::Env) -> Type {
|
||||
static TO_STRING: java::Method<MessageType, fn() -> String> = java::Method::new("toString");
|
||||
|
||||
match TO_STRING.invoke(env, self).trim().to_uppercase().as_str() {
|
||||
| "CON" => Type::Con,
|
||||
| "NON" => Type::Non,
|
||||
| "ACK" => Type::Ack,
|
||||
| "RESET" => Type::Reset,
|
||||
| o => panic!("malformed message type {}", o),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
use jni::objects::{JClass, JObject};
|
||||
use jni::sys::jobject;
|
||||
use toad::platform::Platform;
|
||||
use toad_jni::java::{self, Object};
|
||||
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
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 new(e: &mut java::Env, cfg: RuntimeConfig) -> Self {
|
||||
static CTOR: java::Constructor<Runtime, fn(RuntimeConfig)> = java::Constructor::new();
|
||||
CTOR.invoke(e, cfg)
|
||||
}
|
||||
|
||||
pub fn poll_req(&self, e: &mut java::Env) -> Option<MessageRef> {
|
||||
static POLL_REQ: java::Method<Runtime, fn() -> java::util::Optional<MessageRef>> =
|
||||
java::Method::new("pollReq");
|
||||
POLL_REQ.invoke(e, self).to_option(e)
|
||||
}
|
||||
|
||||
pub fn config(&self, e: &mut java::Env) -> RuntimeConfig {
|
||||
static CONFIG: java::Method<Runtime, fn() -> RuntimeConfig> = java::Method::new("config");
|
||||
CONFIG.invoke(e, self)
|
||||
}
|
||||
|
||||
fn init_impl(e: &mut java::Env, cfg: RuntimeConfig) -> i64 {
|
||||
let r = || ToadRuntime::try_new(cfg.addr(e), cfg.to_toad(e)).unwrap();
|
||||
unsafe { crate::mem::Shared::init(r).addr() as i64 }
|
||||
}
|
||||
|
||||
fn poll_req_impl(e: &mut java::Env, addr: i64) -> java::util::Optional<MessageRef> {
|
||||
match unsafe {
|
||||
Shared::deref::<crate::Runtime>(/* TODO */ 0, addr).as_ref()
|
||||
.unwrap()
|
||||
}.poll_req()
|
||||
{
|
||||
| Ok(req) => {
|
||||
let mr = MessageRef::new(e, req.unwrap().into());
|
||||
java::util::Optional::<MessageRef>::of(e, mr)
|
||||
},
|
||||
| Err(nb::Error::WouldBlock) => java::util::Optional::<MessageRef>::empty(e),
|
||||
| Err(nb::Error::Other(err)) => {
|
||||
e.throw(format!("{:?}", err)).unwrap();
|
||||
java::util::Optional::<MessageRef>::empty(e)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
java::object_newtype!(Runtime);
|
||||
|
||||
impl java::Class for Runtime {
|
||||
const PATH: &'static str = package!(dev.toad.ToadRuntime);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_ToadRuntime_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_impl(e, cfg)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_ToadRuntime_pollReq<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let e = &mut e;
|
||||
Runtime::poll_req_impl(e, addr).yield_to_java(e)
|
||||
}
|
10
src/main/java/dev.toad/Client.java
Normal file
10
src/main/java/dev.toad/Client.java
Normal file
@ -0,0 +1,10 @@
|
||||
package dev.toad;
|
||||
|
||||
public final class Client {
|
||||
|
||||
final Toad toad;
|
||||
|
||||
Client(Toad toad) {
|
||||
this.toad = toad;
|
||||
}
|
||||
}
|
@ -1,46 +1,58 @@
|
||||
package dev.toad;
|
||||
|
||||
import dev.toad.ffi.*;
|
||||
import dev.toad.msg.MessageRef;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ToadRuntime {
|
||||
public final class Toad {
|
||||
|
||||
static native Config defaultConfigImpl();
|
||||
|
||||
static Config defaultConfig = null;
|
||||
|
||||
static Config defaultConfig() {
|
||||
if (ToadRuntime.defaultConfig == null) {
|
||||
ToadRuntime.defaultConfig = ToadRuntime.defaultConfigImpl();
|
||||
if (Toad.defaultConfig == null) {
|
||||
Toad.defaultConfig = Toad.defaultConfigImpl();
|
||||
}
|
||||
|
||||
return ToadRuntime.defaultConfig;
|
||||
return Toad.defaultConfig;
|
||||
}
|
||||
|
||||
static {
|
||||
System.loadLibrary("toad_java_glue");
|
||||
}
|
||||
|
||||
private final Ptr ptr;
|
||||
private final Config config;
|
||||
final Ptr ptr;
|
||||
final Config config;
|
||||
|
||||
private static native long init(Config o);
|
||||
static native long init(Config o);
|
||||
|
||||
private static native Optional<MessageRef> pollReq(long addr);
|
||||
static native Optional<dev.toad.msg.ref.Message> pollReq(long ptr);
|
||||
|
||||
Optional<MessageRef> pollReq() {
|
||||
return ToadRuntime.pollReq(this.ptr.addr());
|
||||
static native Optional<dev.toad.msg.ref.Message> pollResp(
|
||||
long ptr,
|
||||
dev.toad.msg.Token t,
|
||||
InetSocketAddress n
|
||||
);
|
||||
|
||||
Optional<dev.toad.msg.ref.Message> pollReq() {
|
||||
return Toad.pollReq(this.ptr.addr());
|
||||
}
|
||||
|
||||
Optional<dev.toad.msg.ref.Message> pollResp(
|
||||
dev.toad.msg.Token regarding,
|
||||
InetSocketAddress from
|
||||
) {
|
||||
return Toad.pollResp(this.ptr.addr(), regarding, from);
|
||||
}
|
||||
|
||||
public static BuilderRequiresBindToAddress builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
ToadRuntime(Config o) {
|
||||
Toad(Config o) {
|
||||
this.config = o;
|
||||
this.ptr = Ptr.register(this.getClass(), this.init(o));
|
||||
}
|
||||
@ -50,21 +62,21 @@ public class ToadRuntime {
|
||||
}
|
||||
|
||||
public interface BuilderRequiresBindToAddress {
|
||||
ToadRuntime.Builder port(short port);
|
||||
ToadRuntime.Builder address(InetSocketAddress addr);
|
||||
Toad.Builder port(short port);
|
||||
Toad.Builder address(InetSocketAddress addr);
|
||||
}
|
||||
|
||||
public static final class Builder implements BuilderRequiresBindToAddress {
|
||||
|
||||
Config.Msg.Builder msg = Config.Msg.builder();
|
||||
Optional<InetSocketAddress> addr = Optional.empty();
|
||||
u8 concurrency = ToadRuntime.defaultConfig().concurrency;
|
||||
u8 concurrency = Toad.defaultConfig().concurrency;
|
||||
|
||||
Builder() {}
|
||||
|
||||
public ToadRuntime build() {
|
||||
public Toad build() {
|
||||
var cfg = new Config(this.addr.get(), this.concurrency, this.msg.build());
|
||||
return new ToadRuntime(cfg);
|
||||
return new Toad(cfg);
|
||||
}
|
||||
|
||||
public Builder msg(Function<Config.Msg.Builder, Config.Msg.Builder> f) {
|
||||
@ -183,10 +195,10 @@ public class ToadRuntime {
|
||||
|
||||
Con.Builder con = Con.builder();
|
||||
Non.Builder non = Non.builder();
|
||||
u16 tokenSeed = ToadRuntime.defaultConfig().msg.tokenSeed;
|
||||
u16 probingRateBytesPerSecond = ToadRuntime.defaultConfig()
|
||||
u16 tokenSeed = Toad.defaultConfig().msg.tokenSeed;
|
||||
u16 probingRateBytesPerSecond = Toad.defaultConfig()
|
||||
.msg.probingRateBytesPerSecond;
|
||||
Duration multicastResponseLeisure = ToadRuntime.defaultConfig()
|
||||
Duration multicastResponseLeisure = Toad.defaultConfig()
|
||||
.msg.multicastResponseLeisure;
|
||||
|
||||
public Msg build() {
|
||||
@ -275,11 +287,11 @@ public class ToadRuntime {
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
RetryStrategy ackedRetryStrategy = ToadRuntime.defaultConfig()
|
||||
RetryStrategy ackedRetryStrategy = Toad.defaultConfig()
|
||||
.msg.con.ackedRetryStrategy;
|
||||
RetryStrategy unackedRetryStrategy = ToadRuntime.defaultConfig()
|
||||
RetryStrategy unackedRetryStrategy = Toad.defaultConfig()
|
||||
.msg.con.unackedRetryStrategy;
|
||||
u16 maxAttempts = ToadRuntime.defaultConfig().msg.con.maxAttempts;
|
||||
u16 maxAttempts = Toad.defaultConfig().msg.con.maxAttempts;
|
||||
|
||||
public Con build() {
|
||||
return new Con(
|
||||
@ -343,9 +355,9 @@ public class ToadRuntime {
|
||||
|
||||
public static final class Builder {
|
||||
|
||||
RetryStrategy retryStrategy = ToadRuntime.defaultConfig()
|
||||
RetryStrategy retryStrategy = Toad.defaultConfig()
|
||||
.msg.non.retryStrategy;
|
||||
u16 maxAttempts = ToadRuntime.defaultConfig().msg.non.maxAttempts;
|
||||
u16 maxAttempts = Toad.defaultConfig().msg.non.maxAttempts;
|
||||
|
||||
public Non build() {
|
||||
return new Non(this.retryStrategy, this.maxAttempts);
|
@ -1,11 +1,11 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
public class MessageCode {
|
||||
public class Code {
|
||||
|
||||
private final int clazz;
|
||||
private final int detail;
|
||||
|
||||
public MessageCode(int clazz, int detail) {
|
||||
public Code(int clazz, int detail) {
|
||||
this.clazz = clazz;
|
||||
this.detail = detail;
|
||||
}
|
14
src/main/java/dev.toad/msg/Id.java
Normal file
14
src/main/java/dev.toad/msg/Id.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
public final class Id {
|
||||
|
||||
final int id;
|
||||
|
||||
public Id(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int toInt() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
@ -6,15 +6,15 @@ import java.util.List;
|
||||
public interface Message {
|
||||
public InetSocketAddress source();
|
||||
|
||||
public int id();
|
||||
public Id id();
|
||||
|
||||
public byte[] token();
|
||||
public Token token();
|
||||
|
||||
public MessageCode code();
|
||||
public Code code();
|
||||
|
||||
public MessageType type();
|
||||
public Type type();
|
||||
|
||||
public List<MessageOption> options();
|
||||
public List<Option> options();
|
||||
|
||||
public byte[] payloadBytes();
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MessageOption {
|
||||
public long number();
|
||||
|
||||
public List<MessageOptionValue> values();
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MessageOptionOwned implements MessageOption {
|
||||
|
||||
public final long number;
|
||||
public final List<MessageOptionValue> values;
|
||||
|
||||
public MessageOptionOwned(MessageOptionRef ref) {
|
||||
this.number = ref.number();
|
||||
this.values =
|
||||
Arrays
|
||||
.asList(ref.valueRefs())
|
||||
.stream()
|
||||
.map(MessageOptionValueRef::clone)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public long number() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public List<MessageOptionValue> values() {
|
||||
return this.values;
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import dev.toad.ffi.Ptr;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageOptionRef implements MessageOption, AutoCloseable {
|
||||
|
||||
private Ptr ptr;
|
||||
private final long number;
|
||||
|
||||
private native MessageOptionValueRef[] values(long ptr);
|
||||
|
||||
public MessageOptionRef(long addr, long number) {
|
||||
this.ptr = Ptr.register(this.getClass(), addr);
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public long number() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public MessageOptionValueRef[] valueRefs() {
|
||||
return this.values(this.ptr.addr());
|
||||
}
|
||||
|
||||
public List<MessageOptionValue> values() {
|
||||
return Arrays.asList(this.values(this.ptr.addr()));
|
||||
}
|
||||
|
||||
public MessageOption clone() {
|
||||
return new MessageOptionOwned(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.ptr.release();
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MessageOptionValueOwned implements MessageOptionValue {
|
||||
|
||||
public final byte[] bytes;
|
||||
|
||||
public MessageOptionValueOwned(MessageOptionValueRef ref) {
|
||||
this.bytes = ref.asBytes().clone();
|
||||
}
|
||||
|
||||
public byte[] asBytes() {
|
||||
return this.bytes;
|
||||
}
|
||||
|
||||
public String asString() {
|
||||
return new String(this.asBytes());
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MessageOwned implements Message {
|
||||
|
||||
private final InetSocketAddress source;
|
||||
private final int id;
|
||||
private final byte[] token;
|
||||
private final byte[] payload;
|
||||
private final MessageCode code;
|
||||
private final MessageType type;
|
||||
private final List<MessageOption> opts;
|
||||
|
||||
public MessageOwned(MessageRef ref) {
|
||||
this.id = ref.id();
|
||||
this.token = ref.token();
|
||||
this.code = ref.code();
|
||||
this.type = ref.type();
|
||||
this.payload = ref.payloadBytes().clone();
|
||||
this.source = ref.source();
|
||||
|
||||
this.opts =
|
||||
Arrays
|
||||
.asList(ref.optionRefs())
|
||||
.stream()
|
||||
.map(MessageOptionRef::clone)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public InetSocketAddress source() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public byte[] token() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public MessageCode code() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public MessageType type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public List<MessageOption> options() {
|
||||
return this.opts;
|
||||
}
|
||||
|
||||
public byte[] payloadBytes() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
public String payloadString() {
|
||||
return new String(this.payload);
|
||||
}
|
||||
}
|
9
src/main/java/dev.toad/msg/Option.java
Normal file
9
src/main/java/dev.toad/msg/Option.java
Normal file
@ -0,0 +1,9 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface Option {
|
||||
public long number();
|
||||
|
||||
public List<OptionValue> values();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
public interface MessageOptionValue {
|
||||
public interface OptionValue {
|
||||
public byte[] asBytes();
|
||||
|
||||
public String asString();
|
14
src/main/java/dev.toad/msg/Token.java
Normal file
14
src/main/java/dev.toad/msg/Token.java
Normal file
@ -0,0 +1,14 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
public final class Token {
|
||||
|
||||
final byte[] bytes;
|
||||
|
||||
public Token(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
return this.bytes;
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
package dev.toad.msg;
|
||||
|
||||
public enum MessageType {
|
||||
public enum Type {
|
||||
CON(1),
|
||||
NON(2),
|
||||
ACK(3),
|
||||
RESET(4);
|
||||
|
||||
private MessageType(int val) {}
|
||||
private Type(int val) {}
|
||||
|
||||
public String toString() {
|
||||
return switch (this) {
|
||||
@ -18,7 +18,7 @@ public enum MessageType {
|
||||
};
|
||||
}
|
||||
|
||||
public static MessageType fromString(String s) {
|
||||
public static Type fromString(String s) {
|
||||
return switch (s.toLowerCase().trim()) {
|
||||
case "con" -> CON;
|
||||
case "non" -> NON;
|
85
src/main/java/dev.toad/msg/owned/Message.java
Normal file
85
src/main/java/dev.toad/msg/owned/Message.java
Normal file
@ -0,0 +1,85 @@
|
||||
package dev.toad.msg.owned;
|
||||
|
||||
import dev.toad.msg.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Message implements dev.toad.msg.Message {
|
||||
|
||||
final InetSocketAddress source;
|
||||
final Id id;
|
||||
final Token token;
|
||||
final byte[] payload;
|
||||
final Code code;
|
||||
final Type type;
|
||||
final List<dev.toad.msg.Option> opts;
|
||||
|
||||
public Message(
|
||||
InetSocketAddress source,
|
||||
Type type,
|
||||
Code code,
|
||||
Id id,
|
||||
Token token,
|
||||
byte[] payload,
|
||||
List<dev.toad.msg.Option> opts
|
||||
) {
|
||||
this.source = source;
|
||||
this.id = id;
|
||||
this.token = token;
|
||||
this.payload = payload;
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
this.opts = opts;
|
||||
}
|
||||
|
||||
public Message(dev.toad.msg.ref.Message ref) {
|
||||
this(
|
||||
ref.source(),
|
||||
ref.type(),
|
||||
ref.code(),
|
||||
ref.id(),
|
||||
ref.token(),
|
||||
ref.payloadBytes().clone(),
|
||||
Arrays
|
||||
.asList(ref.optionRefs())
|
||||
.stream()
|
||||
.map(dev.toad.msg.ref.Option::clone)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public InetSocketAddress source() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public Id id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public Token token() {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
public Code code() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public List<dev.toad.msg.Option> options() {
|
||||
return this.opts;
|
||||
}
|
||||
|
||||
public byte[] payloadBytes() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
public String payloadString() {
|
||||
return new String(this.payload);
|
||||
}
|
||||
}
|
36
src/main/java/dev.toad/msg/owned/Option.java
Normal file
36
src/main/java/dev.toad/msg/owned/Option.java
Normal file
@ -0,0 +1,36 @@
|
||||
package dev.toad.msg.owned;
|
||||
|
||||
import dev.toad.msg.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Option implements dev.toad.msg.Option {
|
||||
|
||||
final long number;
|
||||
final List<dev.toad.msg.OptionValue> values;
|
||||
|
||||
public Option(long number, List<dev.toad.msg.OptionValue> values) {
|
||||
this.number = number;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public Option(dev.toad.msg.ref.Option ref) {
|
||||
this(
|
||||
ref.number(),
|
||||
Arrays
|
||||
.asList(ref.valueRefs())
|
||||
.stream()
|
||||
.map(dev.toad.msg.ref.OptionValue::clone)
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
}
|
||||
|
||||
public long number() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public List<dev.toad.msg.OptionValue> values() {
|
||||
return this.values;
|
||||
}
|
||||
}
|
22
src/main/java/dev.toad/msg/owned/OptionValue.java
Normal file
22
src/main/java/dev.toad/msg/owned/OptionValue.java
Normal file
@ -0,0 +1,22 @@
|
||||
package dev.toad.msg.owned;
|
||||
|
||||
public class OptionValue implements dev.toad.msg.OptionValue {
|
||||
|
||||
public final byte[] bytes;
|
||||
|
||||
public OptionValue(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public OptionValue(dev.toad.msg.ref.OptionValue ref) {
|
||||
this(ref.asBytes().clone());
|
||||
}
|
||||
|
||||
public byte[] asBytes() {
|
||||
return this.bytes;
|
||||
}
|
||||
|
||||
public String asString() {
|
||||
return new String(this.asBytes());
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package dev.toad.msg;
|
||||
package dev.toad.msg.ref;
|
||||
|
||||
import dev.toad.ffi.Ptr;
|
||||
import dev.toad.msg.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@ -13,32 +14,32 @@ import java.util.Optional;
|
||||
* control is yielded back to the rust runtime, meaning instances of
|
||||
* MessageRef should never be stored in state; invoke `.clone()` first.
|
||||
*/
|
||||
public class MessageRef implements Message, AutoCloseable {
|
||||
public final class Message implements dev.toad.msg.Message, AutoCloseable {
|
||||
|
||||
private Ptr ptr;
|
||||
Ptr ptr;
|
||||
|
||||
private Optional<InetSocketAddress> source = Optional.empty();
|
||||
Optional<InetSocketAddress> source = Optional.empty();
|
||||
|
||||
private static native InetSocketAddress source(long addr);
|
||||
static native InetSocketAddress source(long addr);
|
||||
|
||||
private static native int id(long addr);
|
||||
static native Id id(long addr);
|
||||
|
||||
private static native byte[] token(long addr);
|
||||
static native Token token(long addr);
|
||||
|
||||
private static native byte[] payload(long addr);
|
||||
static native byte[] payload(long addr);
|
||||
|
||||
private static native MessageCode code(long addr);
|
||||
static native Code code(long addr);
|
||||
|
||||
private static native MessageType type(long addr);
|
||||
static native Type type(long addr);
|
||||
|
||||
private static native MessageOptionRef[] opts(long addr);
|
||||
static native dev.toad.msg.ref.Option[] opts(long addr);
|
||||
|
||||
public MessageRef(long addr) {
|
||||
Message(long addr) {
|
||||
this.ptr = Ptr.register(this.getClass(), addr);
|
||||
}
|
||||
|
||||
public Message clone() {
|
||||
return new MessageOwned(this);
|
||||
public dev.toad.msg.Message clone() {
|
||||
return new dev.toad.msg.owned.Message(this);
|
||||
}
|
||||
|
||||
public InetSocketAddress source() {
|
||||
@ -49,27 +50,27 @@ public class MessageRef implements Message, AutoCloseable {
|
||||
return this.source.get();
|
||||
}
|
||||
|
||||
public int id() {
|
||||
public Id id() {
|
||||
return this.id(this.ptr.addr());
|
||||
}
|
||||
|
||||
public byte[] token() {
|
||||
public Token token() {
|
||||
return this.token(this.ptr.addr());
|
||||
}
|
||||
|
||||
public MessageCode code() {
|
||||
public Code code() {
|
||||
return this.code(this.ptr.addr());
|
||||
}
|
||||
|
||||
public MessageType type() {
|
||||
public Type type() {
|
||||
return this.type(this.ptr.addr());
|
||||
}
|
||||
|
||||
public MessageOptionRef[] optionRefs() {
|
||||
public dev.toad.msg.ref.Option[] optionRefs() {
|
||||
return this.opts(this.ptr.addr());
|
||||
}
|
||||
|
||||
public List<MessageOption> options() {
|
||||
public List<dev.toad.msg.Option> options() {
|
||||
return Arrays.asList(this.opts(this.ptr.addr()));
|
||||
}
|
||||
|
40
src/main/java/dev.toad/msg/ref/Option.java
Normal file
40
src/main/java/dev.toad/msg/ref/Option.java
Normal file
@ -0,0 +1,40 @@
|
||||
package dev.toad.msg.ref;
|
||||
|
||||
import dev.toad.ffi.Ptr;
|
||||
import dev.toad.msg.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Option implements dev.toad.msg.Option, AutoCloseable {
|
||||
|
||||
Ptr ptr;
|
||||
final long number;
|
||||
|
||||
native dev.toad.msg.ref.OptionValue[] values(long ptr);
|
||||
|
||||
Option(long addr, long number) {
|
||||
this.ptr = Ptr.register(this.getClass(), addr);
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public long number() {
|
||||
return this.number;
|
||||
}
|
||||
|
||||
public dev.toad.msg.ref.OptionValue[] valueRefs() {
|
||||
return this.values(this.ptr.addr());
|
||||
}
|
||||
|
||||
public List<dev.toad.msg.OptionValue> values() {
|
||||
return Arrays.asList(this.values(this.ptr.addr()));
|
||||
}
|
||||
|
||||
public dev.toad.msg.Option clone() {
|
||||
return new dev.toad.msg.owned.Option(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.ptr.release();
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
package dev.toad.msg;
|
||||
package dev.toad.msg.ref;
|
||||
|
||||
import dev.toad.ffi.Ptr;
|
||||
|
||||
public class MessageOptionValueRef
|
||||
implements MessageOptionValue, AutoCloseable {
|
||||
public final class OptionValue
|
||||
implements dev.toad.msg.OptionValue, AutoCloseable {
|
||||
|
||||
private final Ptr ptr;
|
||||
|
||||
private native byte[] bytes(long addr);
|
||||
|
||||
public MessageOptionValueRef(long addr) {
|
||||
OptionValue(long addr) {
|
||||
this.ptr = Ptr.register(this.getClass(), addr);
|
||||
}
|
||||
|
||||
@ -21,8 +21,8 @@ public class MessageOptionValueRef
|
||||
return new String(this.bytes(this.ptr.addr()));
|
||||
}
|
||||
|
||||
public MessageOptionValue clone() {
|
||||
return this;
|
||||
public dev.toad.msg.OptionValue clone() {
|
||||
return new dev.toad.msg.owned.OptionValue(this);
|
||||
}
|
||||
|
||||
@Override
|
Loading…
Reference in New Issue
Block a user