use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FrameLimit {
local: Option<u32>,
remote: Option<u32>,
}
impl Default for FrameLimit {
fn default() -> Self {
Self { local: Some(Self::LOCAL), remote: Some(Self::REMOTE) }
}
}
impl FrameLimit {
pub const LOCAL: u32 = 60;
pub const REMOTE: u32 = 20;
#[must_use]
pub fn per_second(frames: u32) -> Self {
let frames = (frames > 0).then_some(frames);
Self { local: frames, remote: frames }
}
#[must_use]
pub fn none() -> Self {
Self { local: None, remote: None }
}
#[must_use]
pub fn remote(self, frames: u32) -> Self {
Self { remote: (frames > 0).then_some(frames), ..self }
}
#[must_use]
pub fn frames_per_second(self, remote: bool) -> Option<u32> {
if remote { self.remote } else { self.local }
}
pub(crate) fn gap(self, remote: bool) -> Option<Duration> {
self.frames_per_second(remote).map(|frames| Duration::from_secs(1) / frames)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_default_draws_fewer_frames_over_a_remote_connection() {
let limit = FrameLimit::default();
assert_eq!(limit.frames_per_second(false), Some(60));
assert_eq!(limit.frames_per_second(true), Some(20));
assert_eq!(limit.gap(false), Some(Duration::from_nanos(16_666_666)));
assert_eq!(limit.gap(true), Some(Duration::from_millis(50)));
}
#[test]
fn a_number_given_holds_on_every_connection_until_the_remote_one_is_given_too() {
let same = FrameLimit::per_second(30);
assert_eq!(same.frames_per_second(false), Some(30));
assert_eq!(same.frames_per_second(true), Some(30));
let quieter = same.remote(10);
assert_eq!(quieter.frames_per_second(false), Some(30), "the local number stays");
assert_eq!(quieter.frames_per_second(true), Some(10));
}
#[test]
fn no_limit_and_a_limit_of_zero_frames_both_allow_every_frame() {
assert_eq!(FrameLimit::none().gap(false), None);
assert_eq!(FrameLimit::none().gap(true), None);
assert_eq!(FrameLimit::per_second(0).frames_per_second(false), None, "zero frames would draw nothing");
assert_eq!(FrameLimit::default().remote(0).frames_per_second(true), None);
assert_eq!(FrameLimit::default().remote(0).frames_per_second(false), Some(60), "only the remote one is lifted");
}
}