feat: use Payload in apis
This commit is contained in:
parent
b8e9eaceb0
commit
66a3784627
@ -1,3 +1,4 @@
|
||||
pub mod option;
|
||||
pub mod owned;
|
||||
pub mod ref_;
|
||||
|
||||
@ -7,6 +8,9 @@ use jni::sys::jobject;
|
||||
use toad_jni::java;
|
||||
pub use ty::Type;
|
||||
|
||||
mod payload;
|
||||
pub use payload::Payload;
|
||||
|
||||
mod code;
|
||||
pub use code::Code;
|
||||
|
||||
|
16
glue/src/dev/toad/msg/option/mod.rs
Normal file
16
glue/src/dev/toad/msg/option/mod.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use toad_jni::java;
|
||||
|
||||
use super::owned::Opt;
|
||||
|
||||
pub struct ContentFormat(java::lang::Object);
|
||||
java::object_newtype!(ContentFormat);
|
||||
impl java::Class for ContentFormat {
|
||||
const PATH: &'static str = package!(dev.toad.msg.option.ContentFormat);
|
||||
}
|
||||
|
||||
impl ContentFormat {
|
||||
pub fn new(e: &mut java::Env, o: Opt) -> Self {
|
||||
static CTOR: java::Constructor<ContentFormat, fn(Opt)> = java::Constructor::new();
|
||||
CTOR.invoke(e, o)
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ use toad_jni::java::{self};
|
||||
use toad_msg::{OptNumber, TryIntoBytes};
|
||||
|
||||
use crate::dev::toad::msg::owned::Opt;
|
||||
use crate::dev::toad::msg::{Code, Id, Token, Type};
|
||||
use crate::dev::toad::msg::{Code, Id, Payload, Token, Type};
|
||||
|
||||
pub struct Message(java::lang::Object);
|
||||
|
||||
@ -43,12 +43,9 @@ impl Message {
|
||||
OPTIONS.get(e, self).into_iter().collect()
|
||||
}
|
||||
|
||||
pub fn payload(&self, e: &mut java::Env) -> Vec<u8> {
|
||||
static PAYLOAD: java::Field<Message, Vec<i8>> = java::Field::new("payload");
|
||||
pub fn payload(&self, e: &mut java::Env) -> Payload {
|
||||
static PAYLOAD: java::Field<Message, Payload> = java::Field::new("payload");
|
||||
PAYLOAD.get(e, self)
|
||||
.into_iter()
|
||||
.map(|i| u8::from_be_bytes(i.to_be_bytes()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn addr(&self, e: &mut java::Env) -> Option<InetSocketAddress> {
|
||||
@ -74,7 +71,7 @@ impl Message {
|
||||
.collect())
|
||||
})
|
||||
.collect::<BTreeMap<OptNumber, Vec<toad_msg::OptValue<Vec<u8>>>>>(),
|
||||
payload: toad_msg::Payload(self.payload(e)) }
|
||||
payload: toad_msg::Payload(self.payload(e).bytes(e)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
42
glue/src/dev/toad/msg/payload.rs
Normal file
42
glue/src/dev/toad/msg/payload.rs
Normal file
@ -0,0 +1,42 @@
|
||||
use toad_jni::java;
|
||||
|
||||
use super::option::ContentFormat;
|
||||
|
||||
pub struct Payload(java::lang::Object);
|
||||
java::object_newtype!(Payload);
|
||||
impl java::Class for Payload {
|
||||
const PATH: &'static str = package!(dev.toad.msg.Payload);
|
||||
}
|
||||
|
||||
impl Payload {
|
||||
pub fn new(e: &mut java::Env, bytes: impl IntoIterator<Item = u8>) -> Self {
|
||||
static CTOR: java::Constructor<Payload, fn(Vec<i8>)> = java::Constructor::new();
|
||||
CTOR.invoke(e,
|
||||
bytes.into_iter()
|
||||
.map(|u| i8::from_be_bytes(u.to_be_bytes()))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn new_content_format(e: &mut java::Env, bytes: Vec<u8>, f: ContentFormat) -> Self {
|
||||
static CTOR: java::Constructor<Payload, fn(ContentFormat, Vec<i8>)> = java::Constructor::new();
|
||||
CTOR.invoke(e,
|
||||
f,
|
||||
bytes.into_iter()
|
||||
.map(|u| i8::from_be_bytes(u.to_be_bytes()))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub fn content_format(&self, e: &mut java::Env) -> Option<ContentFormat> {
|
||||
static CONTENT_FORMAT: java::Method<Payload, fn() -> java::util::Optional<ContentFormat>> =
|
||||
java::Method::new("contentFormat");
|
||||
CONTENT_FORMAT.invoke(e, self).to_option(e)
|
||||
}
|
||||
|
||||
pub fn bytes(&self, e: &mut java::Env) -> Vec<u8> {
|
||||
static BYTES: java::Method<Payload, fn() -> Vec<i8>> = java::Method::new("bytes");
|
||||
BYTES.invoke(e, self)
|
||||
.into_iter()
|
||||
.map(|i| u8::from_be_bytes(i.to_be_bytes()))
|
||||
.collect()
|
||||
}
|
||||
}
|
@ -6,10 +6,11 @@ use toad::net::Addrd;
|
||||
use toad_jni::java::lang::Throwable;
|
||||
use toad_jni::java::net::InetSocketAddress;
|
||||
use toad_jni::java::{self, Object, ResultYieldToJavaOrThrow};
|
||||
use toad_msg::MessageOptions;
|
||||
|
||||
use crate::dev::toad::ffi::Ptr;
|
||||
use crate::dev::toad::msg::ref_::Opt;
|
||||
use crate::dev::toad::msg::{Code, Id, Token, Type};
|
||||
use crate::dev::toad::msg::{Code, Id, Payload, Token, Type};
|
||||
use crate::mem::{Shared, SharedMemoryRegion};
|
||||
|
||||
pub struct Message(java::lang::Object);
|
||||
@ -20,9 +21,9 @@ impl java::Class for Message {
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(env: &mut java::Env, msg_addr: i64) -> Self {
|
||||
pub fn new(e: &mut java::Env, msg_addr: i64) -> Self {
|
||||
static CTOR: java::Constructor<Message, fn(i64)> = java::Constructor::new();
|
||||
CTOR.invoke(env, msg_addr)
|
||||
CTOR.invoke(e, msg_addr)
|
||||
}
|
||||
|
||||
pub fn ptr(&self, e: &mut java::Env) -> Ptr {
|
||||
@ -39,73 +40,68 @@ impl Message {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_toad(&self, env: &mut java::Env) -> Addrd<toad_msg::alloc::Message> {
|
||||
let msg = toad_msg::alloc::Message { ty: self.ty(env),
|
||||
pub fn to_toad(&self, e: &mut java::Env) -> Addrd<toad_msg::alloc::Message> {
|
||||
let msg = toad_msg::alloc::Message { ty: self.ty(e),
|
||||
ver: toad_msg::Version::default(),
|
||||
code: self.code(env),
|
||||
id: self.id(env),
|
||||
token: self.token(env),
|
||||
payload: toad_msg::Payload(self.payload(env)),
|
||||
opts: self.options(env)
|
||||
code: self.code(e),
|
||||
id: self.id(e),
|
||||
token: self.token(e),
|
||||
payload: toad_msg::Payload(self.payload(e).bytes(e)),
|
||||
opts: self.options(e)
|
||||
.into_iter()
|
||||
.map(|opt| {
|
||||
(opt.number(env),
|
||||
opt.values(env)
|
||||
(opt.number(e),
|
||||
opt.values(e)
|
||||
.into_iter()
|
||||
.map(|v| toad_msg::OptValue(v.bytes(env)))
|
||||
.map(|v| toad_msg::OptValue(v.bytes(e)))
|
||||
.collect())
|
||||
})
|
||||
.collect::<BTreeMap<toad_msg::OptNumber,
|
||||
Vec<toad_msg::OptValue<Vec<u8>>>>>() };
|
||||
Addrd(msg,
|
||||
self.addr(env)
|
||||
self.addr(e)
|
||||
.expect("java should have made sure the address was present"))
|
||||
}
|
||||
|
||||
pub fn close(&self, env: &mut java::Env) {
|
||||
pub fn close(&self, e: &mut java::Env) {
|
||||
static CLOSE: java::Method<Message, fn()> = java::Method::new("close");
|
||||
CLOSE.invoke(env, self)
|
||||
CLOSE.invoke(e, self)
|
||||
}
|
||||
|
||||
pub fn addr(&self, env: &mut java::Env) -> Option<no_std_net::SocketAddr> {
|
||||
pub fn addr(&self, e: &mut java::Env) -> Option<no_std_net::SocketAddr> {
|
||||
static SOURCE: java::Method<Message, fn() -> java::util::Optional<InetSocketAddress>> =
|
||||
java::Method::new("addr");
|
||||
SOURCE.invoke(env, self)
|
||||
.to_option(env)
|
||||
.map(|a| a.to_no_std(env))
|
||||
SOURCE.invoke(e, self).to_option(e).map(|a| a.to_no_std(e))
|
||||
}
|
||||
|
||||
pub fn ty(&self, env: &mut java::Env) -> toad_msg::Type {
|
||||
pub fn ty(&self, e: &mut java::Env) -> toad_msg::Type {
|
||||
static TYPE: java::Method<Message, fn() -> Type> = java::Method::new("type");
|
||||
TYPE.invoke(env, self).to_toad(env)
|
||||
TYPE.invoke(e, self).to_toad(e)
|
||||
}
|
||||
|
||||
pub fn id(&self, env: &mut java::Env) -> toad_msg::Id {
|
||||
pub fn id(&self, e: &mut java::Env) -> toad_msg::Id {
|
||||
static ID: java::Method<Message, fn() -> Id> = java::Method::new("id");
|
||||
ID.invoke(env, self).to_toad(env)
|
||||
ID.invoke(e, self).to_toad(e)
|
||||
}
|
||||
|
||||
pub fn token(&self, env: &mut java::Env) -> toad_msg::Token {
|
||||
pub fn token(&self, e: &mut java::Env) -> toad_msg::Token {
|
||||
static TOKEN: java::Method<Message, fn() -> Token> = java::Method::new("token");
|
||||
TOKEN.invoke(env, self).to_toad(env)
|
||||
TOKEN.invoke(e, self).to_toad(e)
|
||||
}
|
||||
|
||||
pub fn code(&self, env: &mut java::Env) -> toad_msg::Code {
|
||||
pub fn code(&self, e: &mut java::Env) -> toad_msg::Code {
|
||||
static CODE: java::Method<Message, fn() -> Code> = java::Method::new("code");
|
||||
CODE.invoke(env, self).to_toad(env)
|
||||
CODE.invoke(e, self).to_toad(e)
|
||||
}
|
||||
|
||||
pub fn options(&self, env: &mut java::Env) -> Vec<Opt> {
|
||||
pub fn options(&self, e: &mut java::Env) -> Vec<Opt> {
|
||||
static OPTIONS: java::Method<Message, fn() -> Vec<Opt>> = java::Method::new("optionRefs");
|
||||
OPTIONS.invoke(env, self)
|
||||
OPTIONS.invoke(e, self)
|
||||
}
|
||||
|
||||
pub fn payload(&self, env: &mut java::Env) -> Vec<u8> {
|
||||
static PAYLOAD: java::Method<Message, fn() -> Vec<i8>> = java::Method::new("payloadBytes");
|
||||
PAYLOAD.invoke(env, self)
|
||||
.into_iter()
|
||||
.map(|i| u8::from_be_bytes(i.to_be_bytes()))
|
||||
.collect()
|
||||
pub fn payload(&self, e: &mut java::Env) -> Payload {
|
||||
static PAYLOAD: java::Method<Message, fn() -> Payload> = java::Method::new("payload");
|
||||
PAYLOAD.invoke(e, self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,15 +128,21 @@ pub extern "system" fn Java_dev_toad_msg_ref_Message_token<'local>(mut env: java
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_payloadBytes<'local>(mut env: java::Env<'local>,
|
||||
msg: JObject<'local>)
|
||||
-> jobject {
|
||||
pub extern "system" fn Java_dev_toad_msg_ref_Message_payload<'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)
|
||||
.try_deref(e)
|
||||
.map(|msg| {
|
||||
java::lang::Object::from_local(e, e.byte_array_from_slice(&msg.data().payload.0)
|
||||
.unwrap())
|
||||
msg.data()
|
||||
.content_format()
|
||||
.map(|f| {
|
||||
Payload::new(e, msg.data().payload.0.iter().copied())
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
Payload::new(e, msg.data().payload.0.iter().copied())
|
||||
})
|
||||
})
|
||||
.yield_to_java_or_throw(e)
|
||||
}
|
||||
|
@ -26,9 +26,7 @@ public interface Message {
|
||||
|
||||
public List<Option> options();
|
||||
|
||||
public byte[] payloadBytes();
|
||||
|
||||
public String payloadString();
|
||||
public Payload payload();
|
||||
|
||||
public dev.toad.msg.owned.Message toOwned();
|
||||
|
||||
|
@ -9,6 +9,11 @@ public final class Payload {
|
||||
final byte[] bytes;
|
||||
final Optional<ContentFormat> contentFormat;
|
||||
|
||||
public Payload() {
|
||||
this.contentFormat = Optional.empty();
|
||||
this.bytes = new byte[] {};
|
||||
}
|
||||
|
||||
public Payload(byte[] bytes) {
|
||||
this.contentFormat = Optional.empty();
|
||||
this.bytes = bytes;
|
||||
|
@ -110,7 +110,7 @@ public final class Message
|
||||
this.code.get(),
|
||||
this.id.orElse(Id.defaultId()),
|
||||
this.token.orElse(Token.defaultToken()),
|
||||
this.payload.map(p -> p.bytes()).orElse(new byte[] {}),
|
||||
this.payload.orElse(new Payload()),
|
||||
this.options.entrySet()
|
||||
.stream()
|
||||
.map(ent -> new dev.toad.msg.owned.Option(ent.getKey(), ent.getValue()))
|
||||
|
@ -15,7 +15,7 @@ public class Message implements dev.toad.msg.Message {
|
||||
final Optional<InetSocketAddress> addr;
|
||||
final Id id;
|
||||
final Token token;
|
||||
final byte[] payload;
|
||||
final Payload payload;
|
||||
final Code code;
|
||||
final Type type;
|
||||
final ArrayList<dev.toad.msg.owned.Option> opts;
|
||||
@ -26,7 +26,7 @@ public class Message implements dev.toad.msg.Message {
|
||||
Code code,
|
||||
Id id,
|
||||
Token token,
|
||||
byte[] payload,
|
||||
Payload payload,
|
||||
ArrayList<dev.toad.msg.owned.Option> opts
|
||||
) {
|
||||
this.addr = addr;
|
||||
@ -45,7 +45,7 @@ public class Message implements dev.toad.msg.Message {
|
||||
ref.code(),
|
||||
ref.id(),
|
||||
ref.token(),
|
||||
ref.payloadBytes().clone(),
|
||||
ref.payload(),
|
||||
Arrays
|
||||
.asList(ref.optionRefs())
|
||||
.stream()
|
||||
@ -82,11 +82,7 @@ public class Message implements dev.toad.msg.Message {
|
||||
return List.copyOf(this.opts);
|
||||
}
|
||||
|
||||
public byte[] payloadBytes() {
|
||||
public Payload payload() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
public String payloadString() {
|
||||
return new String(this.payload);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public final class Message implements dev.toad.msg.Message, AutoCloseable {
|
||||
|
||||
public native Token token();
|
||||
|
||||
public native byte[] payloadBytes();
|
||||
public native Payload payload();
|
||||
|
||||
public native Code code();
|
||||
|
||||
@ -46,10 +46,6 @@ public final class Message implements dev.toad.msg.Message, AutoCloseable {
|
||||
return Arrays.asList(this.optionRefs());
|
||||
}
|
||||
|
||||
public String payloadString() {
|
||||
return new String(this.payloadBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.ptr.release();
|
||||
|
@ -45,6 +45,6 @@ class E2E extends munit.FunSuite {
|
||||
|
||||
val respActual = respFuture.get(1, TimeUnit.SECONDS)
|
||||
|
||||
assertEquals(resp.payloadBytes().toSeq, respActual.payloadBytes().toSeq)
|
||||
assertEquals(resp.payload.bytes.toSeq, respActual.payload.bytes.toSeq)
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import dev.toad.msg.option.Path
|
||||
import dev.toad.msg.option.Query
|
||||
|
||||
class MessageBuilder extends munit.FunSuite {
|
||||
test("payload sets content format") {
|
||||
test("payload(Payload) sets content format to ContentFormat.JSON") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost")
|
||||
@ -18,7 +18,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.getContentFormat.get, ContentFormat.JSON)
|
||||
}
|
||||
|
||||
test("uri uses system DNS to resolve host address") {
|
||||
test("uri(String) uses system DNS to resolve host address") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost")
|
||||
@ -29,7 +29,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.addr.get.getAddress.getHostAddress, "127.0.0.1");
|
||||
}
|
||||
|
||||
test("uri gets port from URI") {
|
||||
test("uri(String) gets port from URI") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost:1234")
|
||||
@ -40,7 +40,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.addr.get.getPort, 1234)
|
||||
}
|
||||
|
||||
test("uri gets port 5683 from scheme coap://") {
|
||||
test("uri(String) gets port 5683 from scheme coap://") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost")
|
||||
@ -51,7 +51,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.addr.get.getPort, 5683)
|
||||
}
|
||||
|
||||
test("uri gets port 5684 from scheme coaps://") {
|
||||
test("uri(String) gets port 5684 from scheme coaps://") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coaps://localhost/cheese/gruyere?foo=bar&bingus")
|
||||
@ -62,7 +62,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.addr.get.getPort, 5684)
|
||||
}
|
||||
|
||||
test("uri sets host to host section of uri") {
|
||||
test("uri(String) sets host to host section of uri") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost/cheese/gruyere?foo=bar&bingus")
|
||||
@ -73,7 +73,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
assertEquals(msg.getHost.get.toString, "localhost")
|
||||
}
|
||||
|
||||
test("uri sets path to path section of uri") {
|
||||
test("uri(String) sets path to path section of uri") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost/cheese/gruyere?foo=bar&bingus")
|
||||
@ -87,7 +87,7 @@ class MessageBuilder extends munit.FunSuite {
|
||||
)
|
||||
}
|
||||
|
||||
test("uri sets query to query section of uri") {
|
||||
test("uri(String) sets query to query section of uri") {
|
||||
val msg = dev.toad.msg.build.Message
|
||||
.builder()
|
||||
.uri("coap://localhost/cheese/gruyere?foo=bar&bingus")
|
||||
|
Loading…
Reference in New Issue
Block a user