use super::errs;
use std::ops::RangeInclusive;
use std::time::Duration;
#[derive(Debug, Clone, Hash)]
#[non_exhaustive]
pub enum HeartbeatRule {
Exact(Duration),
Range(RangeInclusive<Duration>),
Any,
}
impl HeartbeatRule {
pub fn validate(&self, proposal: &Duration) -> std::result::Result<(), String> {
match self {
HeartbeatRule::Exact(expected) => {
if proposal == expected {
Ok(())
} else {
Err(errs::heartbeat_exact(expected.as_secs()))
}
}
HeartbeatRule::Range(range) => {
if range.contains(proposal) {
Ok(())
} else {
Err(errs::heartbeat_range(
range.start().as_secs(),
range.end().as_secs(),
))
}
}
HeartbeatRule::Any => {
if *proposal != Duration::from_secs(0) {
Ok(())
} else {
Err(errs::heartbeat_gt_0())
}
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn heartebeat_validation() {
let rule_exact_1 = HeartbeatRule::Exact(Duration::from_secs(1));
let rule_range_5_30 =
HeartbeatRule::Range(Duration::from_secs(5)..=Duration::from_secs(30));
let rule_any = HeartbeatRule::Any;
assert!(rule_exact_1.validate(&Duration::from_secs(1)).is_ok());
assert!(!rule_exact_1.validate(&Duration::from_secs(2)).is_ok());
assert!(!rule_exact_1.validate(&Duration::from_secs(0)).is_ok());
assert!(rule_range_5_30.validate(&Duration::from_secs(5)).is_ok());
assert!(rule_range_5_30.validate(&Duration::from_secs(10)).is_ok());
assert!(rule_range_5_30.validate(&Duration::from_secs(30)).is_ok());
assert!(!rule_range_5_30.validate(&Duration::from_secs(0)).is_ok());
assert!(!rule_range_5_30.validate(&Duration::from_secs(4)).is_ok());
assert!(!rule_range_5_30.validate(&Duration::from_secs(60)).is_ok());
assert!(rule_any.validate(&Duration::from_secs(1)).is_ok());
assert!(!rule_any.validate(&Duration::from_secs(0)).is_ok());
}
}