use std::{ops::RangeInclusive, time::SystemTime};
use rand::{rngs::SmallRng, SeedableRng};
#[cfg(feature = "unstable-fs")]
use crate::fs::FsConfig;
use crate::*;
pub struct Builder {
config: Config,
ip_version: IpVersion,
link: config::Link,
rng_seed: Option<u64>,
}
impl Default for Builder {
fn default() -> Self {
Self::new()
}
}
impl Builder {
pub fn new() -> Self {
Self {
config: Config::default(),
ip_version: IpVersion::default(),
link: config::Link {
latency: Some(config::Latency::default()),
message_loss: Some(config::MessageLoss::default()),
},
rng_seed: None,
}
}
pub fn epoch(&mut self, value: SystemTime) -> &mut Self {
self.config.epoch = value;
self
}
pub fn simulation_duration(&mut self, value: Duration) -> &mut Self {
self.config.duration = value;
self
}
pub fn tick_duration(&mut self, value: Duration) -> &mut Self {
self.config.tick = value;
self
}
pub fn ip_version(&mut self, value: IpVersion) -> &mut Self {
self.ip_version = value;
self
}
pub fn min_message_latency(&mut self, value: Duration) -> &mut Self {
self.link.latency_mut().min_message_latency = value;
self
}
pub fn max_message_latency(&mut self, value: Duration) -> &mut Self {
self.link.latency_mut().max_message_latency = value;
self
}
pub fn fail_rate(&mut self, value: f64) -> &mut Self {
self.link.message_loss_mut().fail_rate = value;
self
}
pub fn repair_rate(&mut self, value: f64) -> &mut Self {
self.link.message_loss_mut().repair_rate = value;
self
}
pub fn ephemeral_ports(&mut self, value: RangeInclusive<u16>) -> &mut Self {
self.config.ephemeral_ports = value;
self
}
pub fn tcp_capacity(&mut self, value: usize) -> &mut Self {
self.config.tcp_capacity = value;
self
}
pub fn udp_capacity(&mut self, value: usize) -> &mut Self {
self.config.udp_capacity = value;
self
}
pub fn enable_tokio_io(&mut self) -> &mut Self {
self.config.enable_tokio_io = true;
self
}
pub fn enable_random_order(&mut self) -> &mut Self {
self.config.random_node_order = true;
self
}
#[cfg(feature = "unstable-fs")]
pub fn fs(&mut self) -> &mut FsConfig {
&mut self.config.fs
}
pub fn rng_seed(&mut self, value: u64) -> &mut Self {
self.rng_seed = Some(value);
self
}
pub fn build<'a>(&self) -> Sim<'a> {
if self.link.latency().max_message_latency < self.link.latency().min_message_latency {
panic!("Maximum message latency must be greater than minimum.");
}
let rng = match self.rng_seed {
Some(seed) => SmallRng::seed_from_u64(seed),
None => SmallRng::from_os_rng(),
};
let world = World::new(
self.link.clone(),
Box::new(rng),
self.ip_version.iter(),
self.config.tick,
);
Sim::new(self.config.clone(), world)
}
}
#[cfg(test)]
mod tests {
use std::time::Duration;
use crate::Builder;
#[test]
#[should_panic]
fn invalid_latency() {
let _sim = Builder::new()
.min_message_latency(Duration::from_millis(100))
.max_message_latency(Duration::from_millis(50))
.build();
}
}