use std::num::NonZeroUsize;
use super::frame_rate::FrameRate;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RuntimeConfig {
pub(crate) frame_rate: FrameRate,
pub(crate) app_channel_capacity: Option<NonZeroUsize>,
pub(crate) keyed_channel_capacity: Option<NonZeroUsize>,
pub(crate) batch_max_messages: Option<NonZeroUsize>,
}
impl RuntimeConfig {
#[must_use]
pub const fn new(frame_rate: FrameRate) -> Self {
Self {
frame_rate,
app_channel_capacity: None,
keyed_channel_capacity: None,
batch_max_messages: None,
}
}
#[must_use = "app_channel_capacity returns a modified config and does not mutate in place"]
pub const fn app_channel_capacity(mut self, capacity: NonZeroUsize) -> Self {
self.app_channel_capacity = Some(capacity);
self
}
#[must_use = "keyed_channel_capacity returns a modified config and does not mutate in place"]
pub const fn keyed_channel_capacity(mut self, capacity: NonZeroUsize) -> Self {
self.keyed_channel_capacity = Some(capacity);
self
}
#[must_use = "batch_max_messages returns a modified config and does not mutate in place"]
pub const fn batch_max_messages(mut self, max: NonZeroUsize) -> Self {
self.batch_max_messages = Some(max);
self
}
}
#[cfg(test)]
mod tests {
use std::num::{NonZeroU32, NonZeroUsize};
use super::*;
fn frame_rate(value: u32) -> FrameRate {
FrameRate::new(NonZeroU32::new(value).expect("frame rate must be non-zero"))
.expect("frame rate must be valid")
}
fn cap(value: usize) -> NonZeroUsize {
NonZeroUsize::new(value).expect("capacity must be non-zero")
}
#[test]
fn new_carries_frame_rate_and_leaves_controls_unset() {
let config = RuntimeConfig::new(frame_rate(60));
assert_eq!(config.frame_rate, frame_rate(60));
assert_eq!(config.app_channel_capacity, None);
assert_eq!(config.keyed_channel_capacity, None);
assert_eq!(config.batch_max_messages, None);
}
#[test]
fn app_channel_capacity_sets_only_its_field() {
let config = RuntimeConfig::new(frame_rate(60)).app_channel_capacity(cap(1024));
assert_eq!(config.app_channel_capacity, Some(cap(1024)));
assert_eq!(config.frame_rate, frame_rate(60));
assert_eq!(config.keyed_channel_capacity, None);
assert_eq!(config.batch_max_messages, None);
}
#[test]
fn keyed_channel_capacity_sets_only_its_field() {
let config = RuntimeConfig::new(frame_rate(60)).keyed_channel_capacity(cap(16));
assert_eq!(config.keyed_channel_capacity, Some(cap(16)));
assert_eq!(config.frame_rate, frame_rate(60));
assert_eq!(config.app_channel_capacity, None);
assert_eq!(config.batch_max_messages, None);
}
#[test]
fn batch_max_messages_sets_only_its_field() {
let config = RuntimeConfig::new(frame_rate(60)).batch_max_messages(cap(8));
assert_eq!(config.batch_max_messages, Some(cap(8)));
assert_eq!(config.frame_rate, frame_rate(60));
assert_eq!(config.app_channel_capacity, None);
assert_eq!(config.keyed_channel_capacity, None);
}
#[test]
fn setters_chain_independently() {
let config = RuntimeConfig::new(frame_rate(30))
.app_channel_capacity(cap(1024))
.keyed_channel_capacity(cap(16))
.batch_max_messages(cap(4));
assert_eq!(config.frame_rate, frame_rate(30));
assert_eq!(config.app_channel_capacity, Some(cap(1024)));
assert_eq!(config.keyed_channel_capacity, Some(cap(16)));
assert_eq!(config.batch_max_messages, Some(cap(4)));
}
#[test]
fn discarded_setter_leaves_original_unmodified() {
let config = RuntimeConfig::new(frame_rate(60));
let _ = config.app_channel_capacity(cap(1024));
assert_eq!(config.app_channel_capacity, None);
}
}