fix: ref msg native fns should be instance methods
This commit is contained in:
parent
618133f5f1
commit
72285ad7a1
@ -1,2 +1,5 @@
|
||||
mod uint;
|
||||
pub use uint::{u16, u32, u64, u8};
|
||||
|
||||
mod ptr;
|
||||
pub use ptr::Ptr;
|
||||
|
15
glue/src/dev/toad/ffi/ptr.rs
Normal file
15
glue/src/dev/toad/ffi/ptr.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use toad_jni::java::lang::{Long, Throwable};
|
||||
use toad_jni::java::{self};
|
||||
|
||||
pub struct Ptr(java::lang::Object);
|
||||
java::object_newtype!(Ptr);
|
||||
impl java::Class for Ptr {
|
||||
const PATH: &'static str = package!(dev.toad.ffi.Ptr);
|
||||
}
|
||||
|
||||
impl Ptr {
|
||||
pub fn addr(&self, e: &mut java::Env) -> Result<Long, Throwable> {
|
||||
static ADDR: java::Method<Ptr, fn() -> Result<Long, Throwable>> = java::Method::new("addr");
|
||||
ADDR.invoke(e, self)
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use jni::objects::JClass;
|
||||
use jni::objects::{JClass, JObject, JThrowable};
|
||||
use jni::sys::jobject;
|
||||
use toad::net::Addrd;
|
||||
use toad_jni::java::lang::Throwable;
|
||||
use toad_jni::java::net::InetSocketAddress;
|
||||
use toad_jni::java::{self, Object};
|
||||
|
||||
use crate::dev::toad::ffi::Ptr;
|
||||
use crate::dev::toad::msg::ref_::Opt;
|
||||
use crate::dev::toad::msg::{Code, Id, Token, Type};
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
@ -23,6 +25,20 @@ impl Message {
|
||||
CTOR.invoke(env, msg_addr)
|
||||
}
|
||||
|
||||
pub fn ptr(&self, e: &mut java::Env) -> Ptr {
|
||||
static PTR: java::Field<Message, Ptr> = java::Field::new("ptr");
|
||||
PTR.get(e, self)
|
||||
}
|
||||
|
||||
pub fn toad_ref(&self,
|
||||
e: &mut java::Env)
|
||||
-> Result<&'static Addrd<toad_msg::alloc::Message>, Throwable> {
|
||||
self.ptr(e).addr(e).map(|addr| unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr.inner(e)).as_ref()
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_toad(&self, env: &mut java::Env) -> Addrd<toad_msg::alloc::Message> {
|
||||
let msg = toad_msg::alloc::Message { ty: self.ty(env),
|
||||
ver: toad_msg::Version::default(),
|
||||
@ -95,97 +111,131 @@ impl Message {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_id<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let e = &mut env;
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
Id::from_toad(e, msg.data().id).yield_to_java(e)
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| Id::from_toad(e, msg.data().id).yield_to_java(e))
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_token<'local>(mut env: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let e = &mut env;
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
Token::from_toad(e, msg.data().token).yield_to_java(e)
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
Token::from_toad(e, msg.data().token).yield_to_java(e)
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[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 {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
env.byte_array_from_slice(&msg.data().payload.0)
|
||||
.unwrap()
|
||||
.as_raw()
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_payloadBytes<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let e = &mut env;
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
e.byte_array_from_slice(&msg.data().payload.0)
|
||||
.unwrap()
|
||||
.as_raw()
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_typ<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
-> jobject {
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
Type::new(&mut e, msg.data().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)
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_type<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
Code::from_toad(&mut e, msg.data().code).yield_to_java(&mut e)
|
||||
let e = &mut env;
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
Type::from_toad(e, msg.data().ty).yield_to_java(e)
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_addr<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_code<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
InetSocketAddress::from_no_std(&mut e, msg.addr()).yield_to_java(&mut e)
|
||||
let e = &mut env;
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
Code::from_toad(e, msg.data().code).yield_to_java(e)
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_opts<'local>(mut e: java::Env<'local>,
|
||||
_: JClass<'local>,
|
||||
addr: i64)
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_addr<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let msg = unsafe {
|
||||
Shared::deref::<Addrd<toad_msg::alloc::Message>>(addr).as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
let opts = &msg.data().opts;
|
||||
let e = &mut env;
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
let addr = InetSocketAddress::from_no_std(e, msg.addr());
|
||||
java::util::Optional::of(e, addr).yield_to_java(e)
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
let refs = opts.into_iter()
|
||||
.map(|(n, v)| Opt::new(&mut e, v as *const _ as i64, n.0.into()))
|
||||
.collect::<Vec<_>>();
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_optionRefs<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
let e = &mut env;
|
||||
java::lang::Object::from_local(e, msg).upcast_to::<Message>(e)
|
||||
.toad_ref(e)
|
||||
.map(|msg| {
|
||||
let opts = &msg.data().opts;
|
||||
|
||||
refs.yield_to_java(&mut e)
|
||||
let refs =
|
||||
opts.into_iter()
|
||||
.map(|(n, v)| {
|
||||
Opt::new(e, v as *const _ as i64, n.0.into())
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
refs.yield_to_java(e)
|
||||
})
|
||||
.map_err(|err| {
|
||||
let err = JThrowable::from(err.downcast(e).to_local(e));
|
||||
e.throw(err).unwrap()
|
||||
})
|
||||
.unwrap_or(*JObject::null())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -8,7 +8,7 @@ impl java::Class for Type {
|
||||
}
|
||||
|
||||
impl Type {
|
||||
pub fn new(env: &mut java::Env, ty: toad_msg::Type) -> Self {
|
||||
pub fn from_toad(env: &mut java::Env, ty: toad_msg::Type) -> Self {
|
||||
static FROM_STRING: java::StaticMethod<Type, fn(String) -> Type> =
|
||||
java::StaticMethod::new("fromString");
|
||||
|
||||
|
@ -18,16 +18,14 @@ import java.util.Optional;
|
||||
*/
|
||||
public class Ptr {
|
||||
|
||||
private static volatile HashSet<Long> validAddresses = new HashSet<>();
|
||||
|
||||
protected final long addr;
|
||||
private final String clazz;
|
||||
private final String trace;
|
||||
Long addr;
|
||||
final String clazz;
|
||||
final String trace;
|
||||
|
||||
/**
|
||||
* Associate a class instance with a native pointer
|
||||
*/
|
||||
public static synchronized Ptr register(Class c, long addr) {
|
||||
public static Ptr register(Class c, long addr) {
|
||||
var trace = Thread.currentThread().getStackTrace();
|
||||
var traceStr = Arrays
|
||||
.asList(trace)
|
||||
@ -36,7 +34,6 @@ public class Ptr {
|
||||
.map(StackTraceElement::toString)
|
||||
.reduce("", (s, tr) -> s == "" ? tr : s + "\n\t" + tr);
|
||||
|
||||
Ptr.validAddresses.add(addr);
|
||||
return new Ptr(addr, c.toString(), traceStr);
|
||||
}
|
||||
|
||||
@ -49,21 +46,21 @@ public class Ptr {
|
||||
/**
|
||||
* Invokes the cleaning action on the object associated with an address
|
||||
*/
|
||||
public synchronized void release() {
|
||||
Ptr.validAddresses.remove(this.addr);
|
||||
public void release() {
|
||||
this.addr = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw `ExpiredError` if object has been leaked
|
||||
* outside of its appropriate context.
|
||||
*/
|
||||
public synchronized void ensureValid() {
|
||||
if (!Ptr.validAddresses.contains(this.addr)) {
|
||||
public void ensureValid() {
|
||||
if (this.addr == null) {
|
||||
throw new ExpiredError(this);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized long addr() {
|
||||
public Long addr() {
|
||||
this.ensureValid();
|
||||
return this.addr;
|
||||
}
|
||||
|
@ -18,23 +18,21 @@ public final class Message implements dev.toad.msg.Message, AutoCloseable {
|
||||
|
||||
Ptr ptr;
|
||||
|
||||
Optional<InetSocketAddress> addr = Optional.empty();
|
||||
public native Optional<InetSocketAddress> addr();
|
||||
|
||||
static native InetSocketAddress addr(long addr);
|
||||
public native Id id();
|
||||
|
||||
static native Id id(long addr);
|
||||
public native Token token();
|
||||
|
||||
static native Token token(long addr);
|
||||
public native byte[] payloadBytes();
|
||||
|
||||
static native byte[] payload(long addr);
|
||||
public native Code code();
|
||||
|
||||
static native Code code(long addr);
|
||||
public native Type type();
|
||||
|
||||
static native Type typ(long addr);
|
||||
public native dev.toad.msg.ref.Option[] optionRefs();
|
||||
|
||||
static native dev.toad.msg.ref.Option[] opts(long addr);
|
||||
|
||||
static native byte[] toBytes(long addr);
|
||||
public native byte[] toBytes();
|
||||
|
||||
Message(long addr) {
|
||||
this.ptr = Ptr.register(this.getClass(), addr);
|
||||
@ -44,48 +42,12 @@ public final class Message implements dev.toad.msg.Message, AutoCloseable {
|
||||
return new dev.toad.msg.owned.Message(this);
|
||||
}
|
||||
|
||||
public Optional<InetSocketAddress> addr() {
|
||||
if (this.addr.isEmpty()) {
|
||||
this.addr = Optional.of(this.addr(this.ptr.addr()));
|
||||
}
|
||||
|
||||
return this.addr;
|
||||
}
|
||||
|
||||
public Id id() {
|
||||
return this.id(this.ptr.addr());
|
||||
}
|
||||
|
||||
public Token token() {
|
||||
return this.token(this.ptr.addr());
|
||||
}
|
||||
|
||||
public Code code() {
|
||||
return this.code(this.ptr.addr());
|
||||
}
|
||||
|
||||
public Type type() {
|
||||
return this.typ(this.ptr.addr());
|
||||
}
|
||||
|
||||
public dev.toad.msg.ref.Option[] optionRefs() {
|
||||
return this.opts(this.ptr.addr());
|
||||
}
|
||||
|
||||
public List<dev.toad.msg.Option> options() {
|
||||
return Arrays.asList(this.opts(this.ptr.addr()));
|
||||
}
|
||||
|
||||
public byte[] payloadBytes() {
|
||||
return this.payload(this.ptr.addr());
|
||||
return Arrays.asList(this.optionRefs());
|
||||
}
|
||||
|
||||
public String payloadString() {
|
||||
return new String(this.payload(this.ptr.addr()));
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
return this.toBytes(this.ptr.addr());
|
||||
return new String(this.payloadBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user