use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy)]
pub struct Deadline {
absolute: Instant,
}
impl Deadline {
pub fn from_request_ms(ms: u64) -> Self {
Self {
absolute: Instant::now() + Duration::from_millis(ms),
}
}
pub fn now_plus(d: Duration) -> Self {
Self {
absolute: Instant::now() + d,
}
}
pub fn remaining(&self) -> Duration {
self.absolute.saturating_duration_since(Instant::now())
}
pub fn expired(&self) -> bool {
Instant::now() >= self.absolute
}
pub fn overrun(&self) -> Duration {
Instant::now().saturating_duration_since(self.absolute)
}
pub fn absolute(&self) -> Instant {
self.absolute
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fresh_deadline_has_remaining() {
let d = Deadline::from_request_ms(1000);
assert!(d.remaining() > Duration::from_millis(900));
assert!(!d.expired());
}
#[test]
fn zero_ms_is_expired() {
let d = Deadline::from_request_ms(0);
assert!(d.expired());
assert_eq!(d.remaining(), Duration::ZERO);
}
#[test]
fn now_plus_matches_remaining() {
let d = Deadline::now_plus(Duration::from_millis(500));
assert!(d.remaining() > Duration::from_millis(400));
assert!(d.remaining() <= Duration::from_millis(500));
}
}