feat: small commit

This commit is contained in:
Orion Kindel 2023-04-04 15:36:01 -07:00
parent d318388c8f
commit ecf9086b35
Signed by untrusted user who does not match committer: orion
GPG Key ID: 6D4165AE4C928719
33 changed files with 2217 additions and 7 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
toad-jni.so
# macOS
.DS_Store

1
.jvmopts Normal file
View File

@ -0,0 +1 @@
-Dfile.encoding=UTF-8 --enable-preview

2
.scalafmt.conf Normal file
View File

@ -0,0 +1,2 @@
runner.dialect = scala3
version = 3.7.3

1
.tool-versions Normal file
View File

@ -0,0 +1 @@
java openjdk-20

View File

@ -1,12 +1,75 @@
import sys.process._
import java.io.File
import sbt.nio.file.FileTreeView
Global / onChangedBuildSource := ReloadOnSourceChanges
val scala3Version = "3.2.2"
val cargoBuild = taskKey[Unit]("cd ./toad-java-glue-rs; cargo build")
val ejectHeaders = taskKey[Unit]("Generate C headers for FFI")
val fullBuild = taskKey[Unit]("cargoBuild > ejectHeaders")
val glob = settingKey[Map[String, Glob]]("globs")
val path = settingKey[Map[String, String]]("paths")
fork := true
javaOptions += "--enable-preview"
javacOptions ++= Seq("--enable-preview", "--release", "20", "-Xlint:preview")
lazy val root = project
.in(file("."))
.settings(
name := "toad",
version := "0.1.0-SNAPSHOT",
scalaVersion := scala3Version,
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test,
glob := Map(
"java.sources" -> baseDirectory.value.toGlob / "src" / "main" / "java" / ** / "*.java",
"glue.sources" -> baseDirectory.value.toGlob / "toad-java-glue-rs" / "src" / ** / "*.rs"
),
path := Map(
"glue.base" -> (baseDirectory.value / "toad-java-glue-rs").toString,
"glue.target" -> (baseDirectory.value / "toad-java-glue-rs" / "target" / "debug").toString,
"java.classTarget" -> (baseDirectory.value / "target" / "scala-3.2.2" / "classes").toString
),
// Test / compile / javacOptions ++= Seq("--enable-preview", "--release", "20", "-Xlint:preview"),
// Test / run / javaOptions ++= Seq(
// "-Djava.library.path=" + path.value("glue.target"),
// "--enable-preview"
// ),
// Compile / doc / javacOptions ++= Seq("--enable-preview", "--release", "20", "-Xlint:preview"),
// Compile / compile / javacOptions ++= Seq("--enable-preview", "--release", "20", "-Xlint:preview"),
// Compile / run / javaOptions ++= Seq(
// "-Djava.library.path=" + path.value("glue.target"),
// "--enable-preview"
// ),
ejectHeaders := {
val files =
FileTreeView.default.iterator(glob.value("java.sources")).foldLeft("") {
(s, fd) => s + " " + fd._1.toString
}
val cmd =
Seq(
"javac",
"--enable-preview",
"--release 20",
"-h " + path.value("glue.target"),
"-d " + path.value("java.classTarget"),
files
)
.foldLeft("")((s, a) => s + " " + a)
libraryDependencies += "org.scalameta" %% "munit" % "0.7.29" % Test
println(Seq("sh", "-c", cmd) !!)
},
cargoBuild := {
val cmd =
Seq("sh", "-c", "cd toad-java-glue-rs; cargo rustc -- -Awarnings")
println(cmd !!)
},
fullBuild := {
cargoBuild.value
ejectHeaders.value
},
Compile / compile := (Compile / compile dependsOn fullBuild).value,
Compile / compile / watchTriggers += glob.value("glue.sources")
)

View File

@ -0,0 +1,47 @@
package dev.toad;
import java.time.Duration;
import java.util.Optional;
public abstract sealed class RetryStrategy {
@Override
public boolean equals(Object other) {
return switch (this) {
case Exponential self -> switch (other) {
case Exponential e -> e.initMin == self.initMin && e.initMax == self.initMax;
default -> false;
};
case Linear self -> switch (other) {
case Linear e -> e.min == self.min && e.max == self.max;
default -> false;
};
default -> false;
};
}
public final class Exponential extends RetryStrategy {
public final Duration initMin;
public final Duration initMax;
private static native Exponential fromRust(byte[] mem);
private native byte[] toRust();
public Exponential(Duration initMin, Duration initMax) {
this.initMin = initMin;
this.initMax = initMax;
}
}
public final class Linear extends RetryStrategy {
public final Duration min;
public final Duration max;
private static native Linear fromRust(byte[] mem);
private native byte[] toRust();
public Linear(Duration min, Duration max) {
this.min = min;
this.max = max;
}
}
}

View File

@ -0,0 +1,7 @@
package dev.toad;
public class Runtime {
public static native void init(RuntimeOptions o);
private Runtime() {}
}

View File

@ -0,0 +1,318 @@
package dev.toad;
import java.time.Duration;
import java.util.Optional;
import java.util.function.Function;
public final class RuntimeOptions implements Cloneable {
private Net net;
public RuntimeOptions() {
this.net = new Net();
}
@Override
public boolean equals(Object other) {
return switch (other) {
case RuntimeOptions o -> o.net == this.net;
default -> false;
};
}
public Net net() {
return this.net;
}
private RuntimeOptions with(Function<RuntimeOptions, RuntimeOptions> f) {
return f.apply(this.clone());
}
public RuntimeOptions withNet(Function<Net, Net> f) {
return this.with(self -> {
self.net = f.apply(self.net);
return self;
});
}
@Override
public RuntimeOptions clone() {
RuntimeOptions self = new RuntimeOptions();
self.net = this.net.clone();
return self;
}
public final class Net implements Cloneable {
private short port;
private short concurrency;
private Msg msg;
public Net() {
this.port = 5683;
this.concurrency = 1;
this.msg = new Msg();
}
@Override
public boolean equals(Object other) {
return switch (other) {
case Net o -> o.port == this.port &&
o.concurrency == this.concurrency &&
o.msg == this.msg;
default -> false;
};
}
private Net with(Function<Net, Net> f) {
return f.apply(this.clone());
}
@Override
public Net clone() {
Net self = new Net();
self.port = this.port;
self.concurrency = this.concurrency;
self.msg = this.msg.clone();
return self;
}
public short port() {
return this.port;
}
public short concurrency() {
return this.concurrency;
}
public Msg msg() {
return this.msg;
}
public Net withPort(short port) {
return this.with(self -> {
self.port = port;
return self;
});
}
public Net withConcurrency(short conc) {
return this.with(self -> {
self.concurrency = conc;
return self;
});
}
public Net withMsg(Function<Msg, Msg> f) {
return this.with(self -> {
self.msg = f.apply(self.msg);
return self;
});
}
}
public final class Msg implements Cloneable {
private Optional<Integer> tokenSeed = Optional.empty();
private Optional<Integer> probingRateBytesPerSecond = Optional.empty();
private Optional<Duration> multicastResponseLeisure = Optional.empty();
private Con con;
private Non non;
public Msg() {
this.con = new Con();
this.non = new Non();
}
private Msg with(Function<Msg, Msg> f) {
return f.apply(this.clone());
}
@Override
public boolean equals(Object other) {
return switch (other) {
case Msg o -> o.tokenSeed == this.tokenSeed &&
o.probingRateBytesPerSecond == this.probingRateBytesPerSecond &&
o.multicastResponseLeisure == this.multicastResponseLeisure &&
o.con == this.con &&
o.non == this.non;
default -> false;
};
}
@Override
public Msg clone() {
Msg self = new Msg();
self.tokenSeed = this.tokenSeed;
self.probingRateBytesPerSecond = this.probingRateBytesPerSecond;
self.multicastResponseLeisure = this.multicastResponseLeisure;
self.con = this.con.clone();
self.non = this.non.clone();
return self;
}
public Optional<Integer> tokenSeed() {
return this.tokenSeed;
}
public Optional<Integer> probingRateBytesPerSecond() {
return this.probingRateBytesPerSecond;
}
public Optional<Duration> multicastResponseLeisure() {
return this.multicastResponseLeisure;
}
public Con con() {
return this.con;
}
public Non non() {
return this.non;
}
public Msg withTokenSeed(int tokenSeed) {
return this.with(self -> {
self.tokenSeed = Optional.of(tokenSeed);
return self;
});
}
public Msg withProbingRateBytesBerSecond(int bps) {
return this.with(m -> {
m.probingRateBytesPerSecond = Optional.of(bps);
return m;
});
}
public Msg withMulticastResponseLeisure(Duration dur) {
return this.with(m -> {
m.multicastResponseLeisure = Optional.of(dur);
return m;
});
}
public Msg withCon(Function<Con, Con> f) {
return this.with(m -> {
m.con = f.apply(m.con);
return m;
});
}
public Msg withNon(Function<Non, Non> f) {
return this.with(m -> {
m.non = f.apply(m.non);
return m;
});
}
public final class Con implements Cloneable {
private Optional<RetryStrategy> ackedRetryStrategy = Optional.empty();
private Optional<RetryStrategy> unackedRetryStrategy = Optional.empty();
private Optional<Integer> maxAttempts = Optional.empty();
public Con() {}
private Con with(Function<Con, Con> f) {
return f.apply(this.clone());
}
@Override
public boolean equals(Object other) {
return switch (other) {
case Con o -> this.ackedRetryStrategy == o.ackedRetryStrategy &&
this.unackedRetryStrategy == o.unackedRetryStrategy &&
this.maxAttempts == o.maxAttempts;
default -> false;
};
}
public Optional<RetryStrategy> ackedRetryStrategy() {
return this.ackedRetryStrategy;
}
public Optional<RetryStrategy> unackedRetryStrategy() {
return this.unackedRetryStrategy;
}
public Optional<Integer> maxAttempts() {
return this.maxAttempts;
}
public Con withAckedRetryStrategy(RetryStrategy r) {
return this.with(s -> {
s.ackedRetryStrategy = Optional.of(r);
return s;
});
}
public Con withUnackedRetryStrategy(RetryStrategy r) {
return this.with(s -> {
s.unackedRetryStrategy = Optional.of(r);
return s;
});
}
public Con withMaxAttempts(int a) {
return this.with(s -> {
s.maxAttempts = Optional.of(a);
return s;
});
}
@Override
public Con clone() {
return this;
}
}
public final class Non implements Cloneable {
private Optional<RetryStrategy> retryStrategy = Optional.empty();
private Optional<Integer> maxAttempts = Optional.empty();
public Non() {}
@Override
public boolean equals(Object other) {
return switch (other) {
case Non o -> this.retryStrategy == o.retryStrategy &&
this.maxAttempts == o.maxAttempts;
default -> false;
};
}
private Non with(Function<Non, Non> f) {
return f.apply(this.clone());
}
public Optional<RetryStrategy> retryStrategy() {
return this.retryStrategy;
}
public Optional<Integer> maxAttempts() {
return this.maxAttempts;
}
public Non withRetryStrategy(RetryStrategy r) {
return this.with(s -> {
s.retryStrategy = Optional.of(r);
return s;
});
}
public Non withMaxAttempts(int a) {
return this.with(s -> {
s.maxAttempts = Optional.of(a);
return s;
});
}
@Override
public Non clone() {
return this;
}
}
}
}

View File

@ -0,0 +1,13 @@
package dev.toad.msg;
import java.util.List;
public interface Message {
public int id();
public byte[] token();
public MessageCode code();
public MessageType type();
public List<MessageOption> options();
public byte[] payloadBytes();
public String payloadString();
}

View File

@ -0,0 +1,44 @@
package dev.toad.msg;
public class MessageCode {
private final int clazz;
private final int detail;
public MessageCode(int clazz, int detail) {
this.clazz = clazz;
this.detail = detail;
}
@Override
public String toString() {
if (this.isRequest()) {
switch (this.detail) {
case 1:
return "GET";
case 2:
return "PUT";
case 3:
return "POST";
case 4:
return "DELETE";
default:
throw new Error();
}
} else {
return String.format("%d.%d", this.clazz, this.detail);
}
}
public boolean isRequest() {
return this.clazz == 0 && this.detail > 0;
}
public boolean isResponse() {
return this.clazz > 1;
}
public boolean isEmpty() {
return this.clazz == 0 && this.detail == 0;
}
}

View File

@ -0,0 +1,8 @@
package dev.toad.msg;
import java.util.List;
public interface MessageOption {
public long number();
public List<MessageOptionValue> values();
}

View File

@ -0,0 +1,22 @@
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;}
}

View File

@ -0,0 +1,32 @@
package dev.toad.msg;
import java.util.Arrays;
import java.util.List;
public class MessageOptionRef implements MessageOption {
private final long addr;
private final long number;
private native MessageOptionValueRef[] values(long addr);
public MessageOptionRef(long addr, long number) {
this.addr = addr;
this.number = number;
}
public long number() {
return this.number;
}
public MessageOptionValueRef[] valueRefs() {
return this.values(this.addr);
}
public List<MessageOptionValue> values() {
return Arrays.asList(this.values(this.addr));
}
public MessageOption clone() {
return new MessageOptionOwned(this);
}
}

View File

@ -0,0 +1,6 @@
package dev.toad.msg;
public interface MessageOptionValue {
public byte[] asBytes();
public String asString();
}

View File

@ -0,0 +1,22 @@
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());
}
}

View File

@ -0,0 +1,22 @@
package dev.toad.msg;
public class MessageOptionValueRef implements MessageOptionValue {
private final long addr;
private native byte[] bytes(long addr);
public MessageOptionValueRef(long addr) {
this.addr = addr;
}
public byte[] asBytes() {
return this.bytes(this.addr);
}
public String asString() {
return new String(this.bytes(this.addr));
}
public MessageOptionValue clone() {
return this;
}
}

View File

@ -0,0 +1,56 @@
package dev.toad.msg;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MessageOwned implements Message {
private static int id;
private static byte[] token;
private static byte[] payload;
private static MessageCode code;
private static MessageType type;
private static 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.opts = Arrays.asList(ref.optionRefs())
.stream()
.map(MessageOptionRef::clone)
.collect(Collectors.toList());
}
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);
}
}

View File

@ -0,0 +1,62 @@
package dev.toad.msg;
import java.util.Arrays;
import java.util.List;
/**
* A pointer to a [`toad_msg::Message`](https://docs.rs/toad-msg/latest/toad_msg/struct.Message.html)
*
* Note that the pointer is not guaranteed to continue to be valid once
* 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 {
private final long addr;
private static native int id(long addr);
private static native byte[] token(long addr);
private static native byte[] payload(long addr);
private static native MessageCode code(long addr);
private static native MessageType type(long addr);
private static native MessageOptionRef[] opts(long addr);
public MessageRef(long addr) {
this.addr = addr;
}
public Message clone() {
return new MessageOwned(this);
}
public int id() {
return this.id(this.addr);
}
public byte[] token() {
return this.token(this.addr);
}
public MessageCode code() {
return this.code(this.addr);
}
public MessageType type() {
return this.type(this.addr);
}
public MessageOptionRef[] optionRefs() {
return this.opts(this.addr);
}
public List<MessageOption> options() {
return Arrays.asList(this.opts(this.addr));
}
public byte[] payloadBytes() {
return this.payload(this.addr);
}
public String payloadString() {
return new String(this.payload(this.addr));
}
}

View File

@ -0,0 +1,27 @@
package dev.toad.msg;
public enum MessageType {
CON(1), NON(2), ACK(3), RESET(4);
private MessageType(int val) {}
public String toString() {
switch(this) {
case CON: return "CON";
case NON: return "NON";
case ACK: return "ACK";
case RESET: return "RESET";
default: throw new Error();
}
}
public static MessageType fromString(String s) {
switch(s.toLowerCase().trim()) {
case "con": return CON;
case "non": return NON;
case "ack": return ACK;
case "reset": return RESET;
default: throw new Error();
}
}
}

View File

@ -1,5 +0,0 @@
@main def hello: Unit =
println("Hello world!")
println(msg)
def msg = "I was compiled by Scala 3. :)"

792
toad-java-glue-rs/Cargo.lock generated Normal file
View File

@ -0,0 +1,792 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "blake2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
dependencies = [
"digest",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]]
name = "cesu8"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "combine"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
dependencies = [
"bytes",
"memchr",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "embedded-time"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a4b4d10ac48d08bfe3db7688c402baadb244721f30a77ce360bd24c3dffe58"
dependencies = [
"num",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "java-locator"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72cb7c9d00a642469deceff95ca37d0da9ce72d7f8b863edbebdf0aac75093da"
dependencies = [
"glob",
"lazy_static",
]
[[package]]
name = "jni"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
dependencies = [
"cesu8",
"cfg-if",
"combine",
"java-locator",
"jni-sys",
"libloading",
"log",
"thiserror",
"walkdir",
"windows-sys",
]
[[package]]
name = "jni-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "naan"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6154b19920bf4498afaf169c5d619d5b351de6d83f8061c114e17061c1ebc612"
[[package]]
name = "nb"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
[[package]]
name = "no-std-net"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
[[package]]
name = "num"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
dependencies = [
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "openssl"
version = "0.10.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
]
[[package]]
name = "openssl-sys"
version = "0.9.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "paste"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
[[package]]
name = "pkg-config"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d0dd4be24fcdcfeaa12a432d588dc59bbad6cad3510c67e74a2b6b2fc950564"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "regex"
version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "serde"
version = "1.0.159"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
[[package]]
name = "serde_json"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
[[package]]
name = "toad"
version = "0.17.2"
dependencies = [
"embedded-time",
"log",
"naan",
"nb",
"no-std-net",
"openssl",
"paste",
"rand",
"rand_chacha",
"serde",
"serde_json",
"tinyvec",
"toad-array 0.2.3",
"toad-hash",
"toad-len",
"toad-macros",
"toad-map",
"toad-msg 0.15.1",
"toad-stem",
"toad-writable",
]
[[package]]
name = "toad-array"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc3f25d13b8cbfe71fe854ff3c9a8f3f9729a5bd008089bb8dc8378b4ef3578f"
dependencies = [
"tinyvec",
"toad-len",
]
[[package]]
name = "toad-array"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "684a00a1501494fb37b8af23bfdf7b5f0a19ef71963abdf5e19eb4afb505f55a"
dependencies = [
"tinyvec",
"toad-len",
]
[[package]]
name = "toad-cursor"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dee8dde5a719faedaf8509f68a8ae1b72e6f0d96bcdbcd59b92de074fe7c33e"
[[package]]
name = "toad-hash"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df947fa0b5724bb3c4e76d04b318a9466bf78a4880aea21a24f9c313d16b643b"
dependencies = [
"blake2",
]
[[package]]
name = "toad-java-glue"
version = "0.1.0"
dependencies = [
"jni",
"tinyvec",
"toad",
"toad-jni",
"toad-msg 0.18.1",
]
[[package]]
name = "toad-jni"
version = "0.1.0"
dependencies = [
"jni",
"toad-array 0.5.0",
"toad-len",
"toad-stem",
]
[[package]]
name = "toad-len"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819ba7124b9324c03a7043145430b0df5b10374543785d3cc5f773b9c0e36b37"
dependencies = [
"tinyvec",
]
[[package]]
name = "toad-macros"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b7496069c25b7e13b920d5293629d9e285d7a4ed9cd51ebfd2ce94690af779a"
dependencies = [
"quote",
"regex",
"syn 1.0.109",
]
[[package]]
name = "toad-map"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "423d547a014a817ea38dc677ca5e8488edf6aeeda36d69bdfcce5adf7b2a0918"
dependencies = [
"tinyvec",
"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]]
name = "toad-msg"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78ad790094eefd8146fab35178e23b224285fe9b275132a31872c0f74b1a8ff"
dependencies = [
"blake2",
"tinyvec",
"toad-array 0.2.3",
"toad-cursor",
"toad-hash",
"toad-len",
"toad-macros",
"toad-map",
]
[[package]]
name = "toad-stem"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "834a7cc46ed626b24dfb861d3de19cdd666fa945f5bd1b4d2d675551afef927c"
[[package]]
name = "toad-writable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebe82c1076c85774b389e86cb2a2dbb846e35e599e9b42c8f2fc6628593cd0a9"
dependencies = [
"toad-array 0.2.3",
]
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]]
name = "unicode-ident"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
dependencies = [
"same-file",
"winapi-util",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_i686_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"

View File

@ -0,0 +1,15 @@
[package]
name = "toad-java-glue"
version = "0.1.0"
edition = "2021"
publish = false
[lib]
crate_type = ["cdylib"]
[dependencies]
jni = "*"
toad = {path = "../../toad/toad"}
toad-jni = {path = "../../toad/toad-jni"}
toad-msg = "*"
tinyvec = {version = "1.5", default_features = false, features = ["rustc_1_55"]}

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly"

View File

@ -0,0 +1,24 @@
# General
max_width = 100
newline_style = "Unix"
tab_spaces = 2
indent_style = "Visual"
format_code_in_doc_comments = true
format_macro_bodies = true
# Match statements
match_arm_leading_pipes = "Always"
match_block_trailing_comma = true
# Structs
use_field_init_shorthand = true
struct_field_align_threshold = 0
# Enums
enum_discrim_align_threshold = 0
# Imports
group_imports = "StdExternalCrate"
imports_granularity = "Module"
imports_indent = "Visual"
imports_layout = "HorizontalVertical"

View File

@ -0,0 +1,68 @@
#![feature(strict_provenance)]
use jni::objects::{JClass, JObject};
use jni::JNIEnv;
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_rules! package {
// allows global compile-time refactoring if the package name ever changes
(dev.toad.$($thing:ident).+) => {$crate::package!(ext dev.toad.$($thing).+)};
(ext $start:ident.$($thing:ident).+) => {concat!(stringify!($start), $("/", stringify!($thing)),+)};
}
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_config;
// Class: dev_toad_Runtime
// Method: init
// Signature: (Ldev/toad/RuntimeOptions;)V
// JNIEXPORT void JNICALL Java_dev_toad_Runtime_init
// (JNIEnv *, jclass, jobject);
pub unsafe extern "system" fn Java_dev_toad_Runtime_init<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
cfg: JObject<'local>) {
}
#[cfg(test)]
mod tests {
use jni::{InitArgsBuilder, JavaVM};
use crate::runtime_config::RuntimeConfig;
#[test]
fn package() {
assert_eq!(package!(dev.toad.msg.Foo.Bar.Baz),
"dev/toad/msg/Foo/Bar/Baz");
assert_eq!(package!(ext java.lang.String), "java/lang/String");
}
#[test]
fn jvm_tests() {
let jvm =
JavaVM::new(InitArgsBuilder::new().option("--enable-preview")
.option("-Djava.class.path=../target/scala-3.2.2/classes/")
.build()
.unwrap()).unwrap();
jvm.attach_current_thread_permanently();
toad_jni::global::init_with(jvm);
let mut e = toad_jni::global::env();
let e = &mut e;
let r = RuntimeConfig::new(e);
assert_eq!(r.to_toad(e), Default::default());
}
}

View File

@ -0,0 +1,19 @@
use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::Code;
pub struct MessageCode<'local>(pub JObject<'local>);
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 {
let o = env.new_object(Self::ID,
Self::CTOR,
&[i32::from(code.class).into(), i32::from(code.detail).into()])
.unwrap();
Self(o)
}
}

View File

@ -0,0 +1,67 @@
use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::{OptNumber, OptValue};
use crate::message_opt_value_ref::MessageOptValueRef;
use crate::with_runtime_provenance;
pub struct MessageOptRef<'local>(pub JObject<'local>);
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";
pub fn class(env: &mut JNIEnv<'local>) -> JClass<'local> {
env.find_class(Self::ID).unwrap()
}
pub fn new(env: &mut JNIEnv<'local>, addr: i64, num: i64) -> Self {
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into(), num.into()])
.unwrap();
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>>> {
with_runtime_provenance::<Vec<OptValue<Vec<u8>>>>(addr).as_mut()
.unwrap()
}
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageOptionRef_number<'local>(mut env: JNIEnv<'local>,
o: JObject<'local>,
p: i64)
-> i64 {
MessageOptRef(o).number(&mut env).0 as i64
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageOptionRef_values<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
p: i64)
-> jobject {
let o = &MessageOptRef::values_ptr(p);
let value_ref_class = MessageOptValueRef::class(&mut env);
let mut arr = env.new_object_array(o.len() as i32, value_ref_class, JObject::null())
.unwrap();
for (ix, v) in o.iter().enumerate() {
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

@ -0,0 +1,38 @@
use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::{OptNumber, OptValue};
use crate::with_runtime_provenance;
pub struct MessageOptValueRef<'local>(pub JObject<'local>);
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> {
env.find_class(Self::ID).unwrap()
}
pub fn new(env: &mut JNIEnv<'local>, addr: i64) -> Self {
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into()])
.unwrap();
Self(o)
}
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut OptValue<Vec<u8>> {
with_runtime_provenance::<OptValue<Vec<u8>>>(addr).as_mut()
.unwrap()
}
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageOptionValueRef_bytes<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
p: i64)
-> jobject {
env.byte_array_from_slice(MessageOptValueRef::ptr(p).as_bytes())
.unwrap()
.as_raw()
}

View File

@ -0,0 +1,91 @@
use jni::objects::{JClass, JObject};
use jni::sys::jobject;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::alloc::Message;
use crate::message_code::MessageCode;
use crate::message_opt_ref::MessageOptRef;
use crate::message_type::MessageType;
use crate::{with_runtime_provenance, RUNTIME};
pub struct MessageRef<'local>(pub JObject<'local>);
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 {
let o = env.new_object(Self::ID, Self::CTOR, &[addr.into()])
.unwrap();
Self(o)
}
pub unsafe fn ptr<'a>(addr: i64) -> &'a mut Message {
with_runtime_provenance::<Message>(addr).as_mut().unwrap()
}
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_id<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> i32 {
MessageRef::ptr(addr).id.0 as i32
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_token<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> jobject {
env.byte_array_from_slice(&MessageRef::ptr(addr).token.0)
.unwrap()
.as_raw()
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_payload<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> jobject {
env.byte_array_from_slice(&MessageRef::ptr(addr).payload.0)
.unwrap()
.as_raw()
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_type<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> jobject {
MessageType::new(&mut env, MessageRef::ptr(addr).ty).0
.into_raw()
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_code<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> jobject {
MessageCode::new(&mut env, MessageRef::ptr(addr).code).0
.into_raw()
}
#[no_mangle]
pub unsafe extern "system" fn Java_dev_toad_msg_MessageRef_opts<'local>(mut env: JNIEnv<'local>,
_: JClass<'local>,
addr: i64)
-> jobject {
let opts = &MessageRef::ptr(addr).opts;
let opt_ref_class = MessageOptRef::class(&mut env);
let mut arr = env.new_object_array((*opts).len() as i32, opt_ref_class, JObject::null())
.unwrap();
for (ix, (num, v)) in (*opts).iter().enumerate() {
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

@ -0,0 +1,32 @@
use jni::objects::{JObject, JString, JValueGen};
use jni::sys::jstring;
use jni::JNIEnv;
use toad_jni::Sig;
use toad_msg::Type;
pub struct MessageType<'local>(pub JObject<'local>);
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 {
let str = env.new_string(match ty {
| Type::Con => "CON",
| Type::Non => "NON",
| Type::Ack => "ACK",
| Type::Reset => "RESET",
})
.unwrap();
let o = env.call_static_method(Self::ID,
"fromString",
Self::FROM_STRING,
&[JValueGen::Object(&str)])
.unwrap()
.l()
.unwrap();
Self(o)
}
}

View File

@ -0,0 +1,52 @@
use jni::objects::{GlobalRef, JObject};
use jni::JNIEnv;
use toad::retry::Strategy;
use toad::time::Millis;
use toad_jni::cls::java;
use toad_jni::convert::Object;
use toad_jni::Sig;
pub struct RetryStrategy(GlobalRef);
impl RetryStrategy {
pub const PATH: &'static str = package!(dev.toad.RetryStrategy);
pub const EXPONENTIAL: &'static str = package!(dev.toad.RetryStrategy.Exponential);
pub const LINEAR: &'static str = package!(dev.toad.RetryStrategy.Linear);
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, "initMax", Sig::class(java::time::Duration::PATH))
.unwrap()
.l()
.unwrap();
let g = e.new_global_ref(o).unwrap();
let d = java::time::Duration::from_java(g);
Millis::new(d.to_millis(e) as u64)
}
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 {
Strategy::Delay { min: self.millis_field(e, "min"),
max: self.millis_field(e, "max") }
}
}
}
impl Object for RetryStrategy {
fn from_java(jobj: GlobalRef) -> Self {
Self(jobj)
}
fn to_java(self) -> GlobalRef {
self.0
}
}

View File

@ -0,0 +1,259 @@
use jni::objects::{GlobalRef, JObject};
use jni::sys::{jint, jshort};
use jni::JNIEnv;
use toad::config::{self, BytesPerSecond};
use toad::retry::{Attempts, Strategy};
use toad::time::Millis;
use toad_jni::cls::java;
use toad_jni::convert::{Object, Primitive};
use toad_jni::Sig;
use crate::retry_strategy::RetryStrategy;
pub struct RuntimeConfig<'a>(JObject<'a>);
impl<'a> RuntimeConfig<'a> {
pub const PATH: &'static str = package!(dev.toad.RuntimeOptions);
pub const CTOR: Sig = Sig::new().returning(Sig::VOID);
pub fn new(e: &mut JNIEnv<'a>) -> Self {
let o = e.new_object(Self::PATH, Self::CTOR, &[]).unwrap();
Self(o)
}
pub fn net(&self, e: &mut JNIEnv<'a>) -> Net<'a> {
let o = e.call_method(&self.0,
"net",
Sig::new().returning(Sig::class(Net::PATH)),
&[])
.unwrap()
.l()
.unwrap();
Net(o)
}
pub fn to_toad(&self, e: &mut JNIEnv<'a>) -> config::Config {
let def = config::Config::default();
let net = self.net(e);
let msg = net.msg(e);
let con = msg.con(e);
let non = msg.non(e);
config::Config { max_concurrent_requests: net.concurrency(e) as u8,
msg: config::Msg { token_seed: msg.token_seed(e)
.map(|i| i as u16)
.unwrap_or(def.msg.token_seed),
probing_rate: msg.probing_rate(e)
.map(|i| BytesPerSecond(i as u16))
.unwrap_or(def.msg.probing_rate),
multicast_response_leisure:
msg.multicast_response_leisure(e)
.unwrap_or(def.msg.multicast_response_leisure),
con:
config::Con { unacked_retry_strategy:
con.unacked_retry_strategy(e)
.unwrap_or(def.msg
.con
.unacked_retry_strategy),
acked_retry_strategy:
con.acked_retry_strategy(e)
.unwrap_or(def.msg
.con
.acked_retry_strategy),
max_attempts:
con.max_attempts(e)
.map(|i| Attempts(i as u16))
.unwrap_or(def.msg.con.max_attempts) },
non: config::Non { retry_strategy:
non.retry_strategy(e)
.unwrap_or(def.msg
.non
.retry_strategy),
max_attempts:
non.max_attempts(e)
.map(|i| Attempts(i as u16))
.unwrap_or(def.msg.non.max_attempts) } } }
}
}
pub struct Net<'a>(JObject<'a>);
impl<'a> Net<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Net");
pub fn port(&self, e: &mut JNIEnv<'a>) -> jshort {
e.call_method(&self.0, "port", Sig::new().returning(Sig::SHORT), &[])
.unwrap()
.s()
.unwrap()
}
pub fn concurrency(&self, e: &mut JNIEnv<'a>) -> jshort {
e.call_method(&self.0,
"concurrency",
Sig::new().returning(Sig::SHORT),
&[])
.unwrap()
.s()
.unwrap()
}
pub fn msg(&self, e: &mut JNIEnv<'a>) -> Msg<'a> {
let o = e.call_method(&self.0,
"msg",
Sig::new().returning(Sig::class(Msg::PATH)),
&[])
.unwrap()
.l()
.unwrap();
Msg(o)
}
}
pub struct Msg<'a>(JObject<'a>);
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));
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> {
let o = e.call_method(&self.0, "tokenSeed", Self::TOKEN_SEED, &[])
.unwrap()
.l()
.unwrap();
let g = e.new_global_ref(o).unwrap();
java::util::Optional::<jint>::from_java(g).to_option(e)
}
pub fn probing_rate(&self, e: &mut JNIEnv<'a>) -> Option<jint> {
let o = e.call_method(&self.0,
"probingRateBytesPerSecond",
Self::PROBING_RATE,
&[])
.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> {
let o = e.call_method(&self.0,
"multicastResponseLeisure",
Self::MULTICAST_RESP_LEISURE,
&[])
.unwrap()
.l()
.unwrap();
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> {
let o = e.call_method(&self.0, "con", Self::CON, &[])
.unwrap()
.l()
.unwrap();
Con(o)
}
pub fn non(&self, e: &mut JNIEnv<'a>) -> Non<'a> {
let o = e.call_method(&self.0, "non", Self::NON, &[])
.unwrap()
.l()
.unwrap();
Non(o)
}
}
pub struct Con<'a>(JObject<'a>);
impl<'a> Con<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Con");
pub const ACKED_RETRY_STRATEGY: Sig =
Sig::new().returning(Sig::class(java::util::Optional::<GlobalRef>::PATH));
pub const UNACKED_RETRY_STRATEGY: Sig =
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> {
let o = e.call_method(&self.0,
"ackedRetryStrategy",
Self::ACKED_RETRY_STRATEGY,
&[])
.unwrap()
.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 unacked_retry_strategy(&self, e: &mut JNIEnv<'a>) -> Option<Strategy> {
let o = e.call_method(&self.0,
"unackedRetryStrategy",
Self::UNACKED_RETRY_STRATEGY,
&[])
.unwrap()
.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> {
let o = e.call_method(&self.0, "maxAttempts", Self::MAX_ATTEMPTS, &[])
.unwrap()
.l()
.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>);
impl<'a> Non<'a> {
pub const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Non");
pub const RETRY_STRATEGY: Sig =
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 retry_strategy(&self, e: &mut JNIEnv<'a>) -> Option<Strategy> {
let o = e.call_method(&self.0, "retryStrategy", Self::RETRY_STRATEGY, &[])
.unwrap()
.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> {
let o = e.call_method(&self.0, "maxAttempts", Self::MAX_ATTEMPTS, &[])
.unwrap()
.l()
.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)
}
}