diff --git a/glue/src/e2e.rs b/glue/src/e2e.rs index 4a6b935..90fac03 100644 --- a/glue/src/e2e.rs +++ b/glue/src/e2e.rs @@ -4,6 +4,7 @@ use std::time::Duration; use jni::objects::GlobalRef; use no_std_net::SocketAddr; +use toad::config::Config; use toad::net::Addrd; use toad::platform::Platform; use toad_jni::java::lang::System; @@ -28,7 +29,7 @@ fn init() -> State { let mut _env = crate::test::init(); let env = &mut _env; - let cfg = RuntimeConfig::new(env); + let cfg = RuntimeConfig::new(env, Config::default(), 5683); let runtime = Runtime::get_or_init(env, cfg); let client = crate::Runtime::try_new("0.0.0.0:5684", Default::default()).unwrap(); diff --git a/glue/src/lib.rs b/glue/src/lib.rs index b487670..e51cca6 100644 --- a/glue/src/lib.rs +++ b/glue/src/lib.rs @@ -45,6 +45,7 @@ pub mod test { use std::sync::Once; use jni::{InitArgsBuilder, JavaVM}; + use toad::config::Config; use toad::retry::Strategy; use toad::time::Millis; use toad_jni::java; @@ -80,8 +81,8 @@ pub mod test { let mut e = init(); let e = &mut e; - let r = RuntimeConfig::new(e); - assert_eq!(r.to_toad(e), Default::default()); + let r = RuntimeConfig::new(e, Config::default(), 5683); + assert_eq!(r.to_toad(e), Config::default()); } #[test] diff --git a/glue/src/mem.rs b/glue/src/mem.rs index 7b74916..1b02e76 100644 --- a/glue/src/mem.rs +++ b/glue/src/mem.rs @@ -53,7 +53,9 @@ struct Mem { pub struct GlobalStatic; impl SharedMemoryRegion for GlobalStatic { unsafe fn dealloc() { - drop(Box::from_raw(MEM)); + if !MEM.is_null() { + drop(Box::from_raw(MEM)); + } } unsafe fn init(r: impl FnOnce() -> crate::Runtime) -> *mut crate::Runtime { diff --git a/glue/src/runtime.rs b/glue/src/runtime.rs index 132516f..3dba9a7 100644 --- a/glue/src/runtime.rs +++ b/glue/src/runtime.rs @@ -36,8 +36,7 @@ impl Runtime { } fn init_impl(e: &mut java::Env, cfg: RuntimeConfig) -> i64 { - let r = - || ToadRuntime::try_new(format!("0.0.0.0:{}", cfg.net(e).port(e)), cfg.to_toad(e)).unwrap(); + let r = || ToadRuntime::try_new(format!("0.0.0.0:{}", cfg.port(e)), cfg.to_toad(e)).unwrap(); unsafe { crate::mem::Shared::init(r).addr() as i64 } } diff --git a/glue/src/runtime_config.rs b/glue/src/runtime_config.rs index 3275b44..93d5b75 100644 --- a/glue/src/runtime_config.rs +++ b/glue/src/runtime_config.rs @@ -1,7 +1,9 @@ -use toad::config::{self, BytesPerSecond}; +use jni::objects::JClass; +use jni::sys::jobject; +use toad::config::{self, BytesPerSecond, Config}; use toad::retry::{Attempts, Strategy}; use toad::time::Millis; -use toad_jni::java; +use toad_jni::java::{self, Class, Object}; use crate::retry_strategy::RetryStrategy; use crate::uint; @@ -10,91 +12,69 @@ pub struct RuntimeConfig(java::lang::Object); java::object_newtype!(RuntimeConfig); impl java::Class for RuntimeConfig { - const PATH: &'static str = package!(dev.toad.RuntimeOptions); + const PATH: &'static str = concat!(package!(dev.toad.Runtime), "$Config"); } impl RuntimeConfig { - pub fn new(e: &mut java::Env) -> Self { - static CTOR: java::Constructor = java::Constructor::new(); - CTOR.invoke(e) - } - - pub fn net(&self, e: &mut java::Env) -> Net { - static NET: java::Method Net> = java::Method::new("net"); - NET.invoke(e, self) - } - - pub fn to_toad(&self, e: &mut java::Env) -> 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(java::lang::Object); -java::object_newtype!(Net); -impl java::Class for Net { - const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Net"); -} - -static NET_PORT: java::Field = java::Field::new("port"); - -impl Net { pub fn port(&self, e: &mut java::Env) -> u16 { - NET_PORT.get(e, self).to_rust(e) - } - - pub fn set_port(&self, e: &mut java::Env, new: u16) { - let new = uint::u16::from_rust(e, new); - NET_PORT.set(e, self, new) + static RUNTIME_CONFIG_PORT: java::Field = java::Field::new("port"); + RUNTIME_CONFIG_PORT.get(e, self).to_rust(e) } pub fn concurrency(&self, e: &mut java::Env) -> u8 { - static CONCURRENCY: java::Field = java::Field::new("concurrency"); - CONCURRENCY.get(e, self).to_rust(e) + static RUNTIME_CONFIG_CONCURRENCY: java::Field = + java::Field::new("concurrency"); + RUNTIME_CONFIG_CONCURRENCY.get(e, self).to_rust(e) } pub fn msg(&self, e: &mut java::Env) -> Msg { - static MSG: java::Method Msg> = java::Method::new("msg"); - MSG.invoke(e, self) + static RUNTIME_CONFIG_MSG: java::Method Msg> = java::Method::new("msg"); + RUNTIME_CONFIG_MSG.invoke(e, self) + } + + pub fn new(e: &mut java::Env, c: Config, port: u16) -> Self { + static CTOR: java::Constructor = + java::Constructor::new(); + + let con = Con::new(e, + c.msg.con.unacked_retry_strategy, + c.msg.con.acked_retry_strategy, + c.msg.con.max_attempts); + let non = Non::new(e, c.msg.non.retry_strategy, c.msg.non.max_attempts); + let msg = Msg::new(e, + c.msg.token_seed, + c.msg.probing_rate.0, + c.msg.multicast_response_leisure, + con, + non); + + let port = uint::u16::from_rust(e, port); + let concurrency = uint::u8::from_rust(e, c.max_concurrent_requests); + + let jcfg = CTOR.invoke(e, port, concurrency, msg); + jcfg + } + + pub fn to_toad(&self, e: &mut java::Env) -> 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 _), + multicast_response_leisure: + msg.multicast_response_leisure(e), + con: 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.retry_strategy(e), + max_attempts: + Attempts(non.max_attempts(e) as _) } } } } } @@ -103,30 +83,49 @@ pub struct Msg(java::lang::Object); java::object_newtype!(Msg); impl java::Class for Msg { - const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg"); + const PATH: &'static str = concat!(package!(dev.toad.Runtime), "$Config$Msg"); } impl Msg { - pub fn token_seed(&self, e: &mut java::Env) -> Option { - static TOKEN_SEED: java::Method java::util::Optional> = - java::Method::new("tokenSeed"); - TOKEN_SEED.invoke(e, self).to_option(e) + pub fn new(e: &mut java::Env, + token_seed: u16, + probe_rate: u16, + multicast_response_leisure: Millis, + con: Con, + non: Non) + -> Self { + static CTOR: java::Constructor = + java::Constructor::new(); + let token_seed = uint::u16::from_rust(e, token_seed); + let probe_rate = uint::u16::from_rust(e, probe_rate); + let multicast_response_leisure = + java::time::Duration::of_millis(e, multicast_response_leisure.0 as i64); + + CTOR.invoke(e, + token_seed, + probe_rate, + multicast_response_leisure, + con, + non) } - pub fn probing_rate(&self, e: &mut java::Env) -> Option { - static PROBING_RATE: java::Method java::util::Optional> = + pub fn token_seed(&self, e: &mut java::Env) -> i32 { + static TOKEN_SEED: java::Method i32> = java::Method::new("tokenSeed"); + TOKEN_SEED.invoke(e, self) + } + + pub fn probing_rate(&self, e: &mut java::Env) -> i32 { + static PROBING_RATE: java::Method i32> = java::Method::new("probingRateBytesPerSecond"); - PROBING_RATE.invoke(e, self).to_option(e) + PROBING_RATE.invoke(e, self) } - pub fn multicast_response_leisure(&self, e: &mut java::Env) -> Option { - static MULTICAST_RESP_LEISURE: java::Method java::util::Optional> = + pub fn multicast_response_leisure(&self, e: &mut java::Env) -> Millis { + static MULTICAST_RESP_LEISURE: java::Method java::time::Duration> = java::Method::new("multicastResponseLeisure"); - MULTICAST_RESP_LEISURE.invoke(e, self) - .to_option(e) - .map(|d| Millis::new(d.to_millis(e) as u64)) + let d = MULTICAST_RESP_LEISURE.invoke(e, self); + + Millis::new(d.to_millis(e) as u64) } pub fn con(&self, e: &mut java::Env) -> Con { @@ -144,30 +143,38 @@ pub struct Con(java::lang::Object); java::object_newtype!(Con); impl java::Class for Con { - const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Con"); + const PATH: &'static str = concat!(package!(dev.toad.Runtime), "$Config$Msg$Con"); } impl Con { - pub fn acked_retry_strategy(&self, e: &mut java::Env) -> Option { - static ACKED_RETRY_STRATEGY: java::Method java::util::Optional> = + pub fn new(e: &mut java::Env, + unacked: toad::retry::Strategy, + acked: toad::retry::Strategy, + max_attempts: Attempts) + -> Self { + static CTOR: java::Constructor = + 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); + CTOR.invoke(e, unacked, acked, att) + } + + pub fn acked_retry_strategy(&self, e: &mut java::Env) -> Strategy { + static ACKED_RETRY_STRATEGY: java::Method RetryStrategy> = java::Method::new("ackedRetryStrategy"); - ACKED_RETRY_STRATEGY.invoke(e, self) - .to_option(e) - .map(|s| s.to_toad(e)) + ACKED_RETRY_STRATEGY.invoke(e, self).to_toad(e) } - pub fn unacked_retry_strategy(&self, e: &mut java::Env) -> Option { - static UNACKED_RETRY_STRATEGY: java::Method java::util::Optional> = + pub fn unacked_retry_strategy(&self, e: &mut java::Env) -> Strategy { + static UNACKED_RETRY_STRATEGY: java::Method RetryStrategy> = java::Method::new("unackedRetryStrategy"); - UNACKED_RETRY_STRATEGY.invoke(e, self) - .to_option(e) - .map(|s| s.to_toad(e)) + UNACKED_RETRY_STRATEGY.invoke(e, self).to_toad(e) } - pub fn max_attempts(&self, e: &mut java::Env) -> Option { - static MAX_ATTEMPTS: java::Method java::util::Optional> = - java::Method::new("maxAttempts"); - MAX_ATTEMPTS.invoke(e, self).to_option(e) + pub fn max_attempts(&self, e: &mut java::Env) -> i32 { + static MAX_ATTEMPTS: java::Method i32> = java::Method::new("maxAttempts"); + MAX_ATTEMPTS.invoke(e, self) } } @@ -175,21 +182,32 @@ pub struct Non(java::lang::Object); java::object_newtype!(Non); impl java::Class for Non { - const PATH: &'static str = concat!(package!(dev.toad.RuntimeOptions), "$Msg$Non"); + const PATH: &'static str = concat!(package!(dev.toad.Runtime), "$Config$Msg$Non"); } impl Non { - pub fn retry_strategy(&self, e: &mut java::Env) -> Option { - static RETRY_STRATEGY: java::Method java::util::Optional> = - java::Method::new("retryStrategy"); - RETRY_STRATEGY.invoke(e, self) - .to_option(e) - .map(|s| s.to_toad(e)) + pub fn new(e: &mut java::Env, strat: toad::retry::Strategy, max_attempts: Attempts) -> Self { + static CTOR: java::Constructor = java::Constructor::new(); + let strat = RetryStrategy::from_toad(e, strat); + let att = uint::u16::from_rust(e, max_attempts.0); + CTOR.invoke(e, strat, att) } - pub fn max_attempts(&self, e: &mut java::Env) -> Option { - static MAX_ATTEMPTS: java::Method java::util::Optional> = - java::Method::new("maxAttempts"); - MAX_ATTEMPTS.invoke(e, self).to_option(e) + pub fn retry_strategy(&self, e: &mut java::Env) -> Strategy { + static RETRY_STRATEGY: java::Method RetryStrategy> = + java::Method::new("retryStrategy"); + RETRY_STRATEGY.invoke(e, self).to_toad(e) + } + + pub fn max_attempts(&self, e: &mut java::Env) -> i32 { + static MAX_ATTEMPTS: java::Method i32> = java::Method::new("maxAttempts"); + MAX_ATTEMPTS.invoke(e, self) } } + +#[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(), 5683).yield_to_java(&mut env) +} diff --git a/src/main/java/dev.toad/Runtime.java b/src/main/java/dev.toad/Runtime.java index f043360..5aaf166 100644 --- a/src/main/java/dev.toad/Runtime.java +++ b/src/main/java/dev.toad/Runtime.java @@ -1,24 +1,340 @@ package dev.toad; +import dev.toad.ffi.*; import dev.toad.msg.MessageRef; +import java.time.Duration; import java.util.Optional; +interface BuilderPort { + Runtime.Config.Builder port(short port); +} + public class Runtime { + + protected static native Config defaultConfigImpl(); + + protected static Config defaultConfig = null; + + protected static Config defaultConfig() { + if (Runtime.defaultConfig == null) { + Runtime.defaultConfig = Runtime.defaultConfigImpl(); + } + + return Runtime.defaultConfig; + } + static { System.loadLibrary("toad_java_glue"); } private final long addr; - private static native long init(RuntimeOptions o); + private static native long init(Config o); private native Optional pollReq(); - public static Runtime getOrInit(RuntimeOptions o) { + public static Runtime getOrInit(Config o) { return new Runtime(o); } - public Runtime(RuntimeOptions o) { + public Runtime(Config o) { this.addr = Runtime.init(o); } + + public static final class Config { + + protected u16 port; + protected u8 concurrency; + protected Msg msg; + + protected Config(u16 port, u8 concurrency, Msg msg) { + this.port = port; + this.concurrency = concurrency; + this.msg = msg; + } + + @Override + public boolean equals(Object other) { + return switch (other) { + case Config o -> o.port == this.port && + o.concurrency == this.concurrency && + o.msg == this.msg; + default -> false; + }; + } + + public int port() { + return this.port.intValue(); + } + + public short concurrency() { + return this.concurrency.shortValue(); + } + + public Msg msg() { + return this.msg; + } + + public static final class Builder implements BuilderPort { + + public final Msg.Builder msg = Msg.builder(); + + protected Optional port = Optional.empty(); + protected u8 concurrency = Runtime.defaultConfig().concurrency; + + protected Builder() {} + + public Config build() { + return new Config(this.port.get(), this.concurrency, this.msg.build()); + } + + public Builder port(short port) { + this.port = Optional.of(new u16(port)); + return this; + } + + public Builder concurrency(byte concurrency) { + this.concurrency = new u8(concurrency); + return this; + } + } + + public static final class Msg { + + protected u16 tokenSeed; + protected u16 probingRateBytesPerSecond; + protected Duration multicastResponseLeisure; + protected Con con; + protected Non non; + + public static Builder builder() { + return new Builder(); + } + + protected Msg( + u16 tokenSeed, + u16 probingRateBytesPerSecond, + Duration multicastResponseLeisure, + Con con, + Non non + ) { + this.tokenSeed = tokenSeed; + this.probingRateBytesPerSecond = probingRateBytesPerSecond; + this.multicastResponseLeisure = multicastResponseLeisure; + this.con = con; + this.non = non; + } + + @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; + }; + } + + public int tokenSeed() { + return this.tokenSeed.intValue(); + } + + public int probingRateBytesPerSecond() { + return this.probingRateBytesPerSecond.intValue(); + } + + public Duration multicastResponseLeisure() { + return this.multicastResponseLeisure; + } + + public Con con() { + return this.con; + } + + public Non non() { + return this.non; + } + + public static final class Builder { + + public final Con.Builder con = Con.builder(); + public final Non.Builder non = Non.builder(); + + protected u16 tokenSeed = Runtime.defaultConfig().msg.tokenSeed; + protected u16 probingRateBytesPerSecond = Runtime.defaultConfig() + .msg.probingRateBytesPerSecond; + protected Duration multicastResponseLeisure = Runtime.defaultConfig() + .msg.multicastResponseLeisure; + + public Msg build() { + return new Msg( + this.tokenSeed, + this.probingRateBytesPerSecond, + this.multicastResponseLeisure, + this.con.build(), + this.non.build() + ); + } + + public Builder tokenSeed(u16 tokenSeed) { + this.tokenSeed = tokenSeed; + return this; + } + + public Builder probingRateBytesPerSecond( + u16 probingRateBytesPerSecond + ) { + this.probingRateBytesPerSecond = probingRateBytesPerSecond; + return this; + } + + public Builder multicastResponseLeisure( + Duration multicastResponseLeisure + ) { + this.multicastResponseLeisure = multicastResponseLeisure; + return this; + } + + protected Builder() {} + } + + public static final class Con { + + protected RetryStrategy ackedRetryStrategy; + protected RetryStrategy unackedRetryStrategy; + protected u16 maxAttempts; + + public static Builder builder() { + return new Builder(); + } + + protected Con( + RetryStrategy unackedRetryStrategy, + RetryStrategy ackedRetryStrategy, + u16 maxAttempts + ) { + this.unackedRetryStrategy = unackedRetryStrategy; + this.ackedRetryStrategy = ackedRetryStrategy; + this.maxAttempts = maxAttempts; + } + + @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 RetryStrategy ackedRetryStrategy() { + return this.ackedRetryStrategy; + } + + public RetryStrategy unackedRetryStrategy() { + return this.unackedRetryStrategy; + } + + public int maxAttempts() { + return this.maxAttempts.intValue(); + } + + public static final class Builder { + + protected RetryStrategy ackedRetryStrategy = Runtime.defaultConfig() + .msg.con.ackedRetryStrategy; + protected RetryStrategy unackedRetryStrategy = Runtime.defaultConfig() + .msg.con.unackedRetryStrategy; + protected u16 maxAttempts = Runtime.defaultConfig() + .msg.con.maxAttempts; + + public Con build() { + return new Con( + this.unackedRetryStrategy, + this.ackedRetryStrategy, + this.maxAttempts + ); + } + + public Builder ackedRetryStrategy(RetryStrategy ackedRetryStrategy) { + this.ackedRetryStrategy = ackedRetryStrategy; + return this; + } + + public Builder unackedRetryStrategy( + RetryStrategy unackedRetryStrategy + ) { + this.unackedRetryStrategy = unackedRetryStrategy; + return this; + } + + public Builder maxAttempts(u16 maxAttempts) { + this.maxAttempts = maxAttempts; + return this; + } + + protected Builder() {} + } + } + + public static final class Non { + + protected RetryStrategy retryStrategy; + protected u16 maxAttempts; + + public static Builder builder() { + return new Builder(); + } + + protected Non(RetryStrategy retryStrategy, u16 maxAttempts) { + this.retryStrategy = retryStrategy; + this.maxAttempts = maxAttempts; + } + + @Override + public boolean equals(Object other) { + return switch (other) { + case Non o -> this.retryStrategy == o.retryStrategy && + this.maxAttempts == o.maxAttempts; + default -> false; + }; + } + + public RetryStrategy retryStrategy() { + return this.retryStrategy; + } + + public int maxAttempts() { + return this.maxAttempts.intValue(); + } + + public static final class Builder { + + protected RetryStrategy retryStrategy = Runtime.defaultConfig() + .msg.non.retryStrategy; + protected u16 maxAttempts = Runtime.defaultConfig() + .msg.non.maxAttempts; + + public Non build() { + return new Non(this.retryStrategy, this.maxAttempts); + } + + public Builder retryStrategy(RetryStrategy retryStrategy) { + this.retryStrategy = retryStrategy; + return this; + } + + public Builder maxAttempts(u16 maxAttempts) { + this.maxAttempts = maxAttempts; + return this; + } + + protected Builder() {} + } + } + } + } } diff --git a/src/main/java/dev.toad/RuntimeOptions.java b/src/main/java/dev.toad/RuntimeOptions.java deleted file mode 100644 index 6d6849c..0000000 --- a/src/main/java/dev.toad/RuntimeOptions.java +++ /dev/null @@ -1,319 +0,0 @@ -package dev.toad; - -import dev.toad.ffi.*; -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 f) { - return f.apply(this.clone()); - } - - public RuntimeOptions withNet(Function 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 u16 port; - private u8 concurrency; - private Msg msg; - - public Net() { - this.port = new u16(5683); - this.concurrency = new u8((short) 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 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 int port() { - return this.port.intValue(); - } - - public short concurrency() { - return this.concurrency.shortValue(); - } - - public Msg msg() { - return this.msg; - } - - public Net withPort(short port) { - return this.with(self -> { - self.port = new u16(port); - return self; - }); - } - - public Net withConcurrency(short conc) { - return this.with(self -> { - self.concurrency = new u8(conc); - return self; - }); - } - - public Net withMsg(Function f) { - return this.with(self -> { - self.msg = f.apply(self.msg); - return self; - }); - } - } - - public final class Msg implements Cloneable { - - private Optional tokenSeed = Optional.empty(); - private Optional probingRateBytesPerSecond = Optional.empty(); - private Optional multicastResponseLeisure = Optional.empty(); - private Con con; - private Non non; - - public Msg() { - this.con = new Con(); - this.non = new Non(); - } - - private Msg with(Function 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 tokenSeed() { - return this.tokenSeed.map(u16 -> u16.intValue()); - } - - public Optional probingRateBytesPerSecond() { - return this.probingRateBytesPerSecond.map(u16 -> u16.intValue()); - } - - public Optional 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(new u16(tokenSeed)); - return self; - }); - } - - public Msg withProbingRateBytesBerSecond(int bps) { - return this.with(m -> { - m.probingRateBytesPerSecond = Optional.of(new u16(bps)); - return m; - }); - } - - public Msg withMulticastResponseLeisure(Duration dur) { - return this.with(m -> { - m.multicastResponseLeisure = Optional.of(dur); - return m; - }); - } - - public Msg withCon(Function f) { - return this.with(m -> { - m.con = f.apply(m.con); - return m; - }); - } - - public Msg withNon(Function f) { - return this.with(m -> { - m.non = f.apply(m.non); - return m; - }); - } - - public final class Con implements Cloneable { - - private Optional ackedRetryStrategy = Optional.empty(); - private Optional unackedRetryStrategy = Optional.empty(); - private Optional maxAttempts = Optional.empty(); - - public Con() {} - - private Con with(Function 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 ackedRetryStrategy() { - return this.ackedRetryStrategy; - } - - public Optional unackedRetryStrategy() { - return this.unackedRetryStrategy; - } - - public Optional maxAttempts() { - return this.maxAttempts.map(u16 -> u16.intValue()); - } - - 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(new u16(a)); - return s; - }); - } - - @Override - public Con clone() { - return this; - } - } - - public final class Non implements Cloneable { - - private Optional retryStrategy = Optional.empty(); - private Optional 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 f) { - return f.apply(this.clone()); - } - - public Optional retryStrategy() { - return this.retryStrategy; - } - - public Optional maxAttempts() { - return this.maxAttempts.map(u16 -> u16.intValue()); - } - - 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(new u16(a)); - return s; - }); - } - - @Override - public Non clone() { - return this; - } - } - } -}