use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct Timeout<T> {
value: Option<T>,
set_time: Option<Instant>,
duration: Duration,
}
impl<T> Timeout<T> {
pub fn new(duration: Duration) -> Self {
Self {
value: None,
set_time: None,
duration,
}
}
pub fn secs(secs: u64) -> Self {
Self::new(Duration::from_secs(secs))
}
pub fn millis(millis: u64) -> Self {
Self::new(Duration::from_millis(millis))
}
pub fn set(&mut self, value: T) {
self.value = Some(value);
self.set_time = Some(Instant::now());
}
pub fn clear(&mut self) {
self.value = None;
self.set_time = None;
}
pub fn is_expired(&self) -> bool {
self.set_time
.map(|t| t.elapsed() > self.duration)
.unwrap_or(false)
}
pub fn get(&self) -> Option<&T> {
self.value.as_ref()
}
pub fn get_mut(&mut self) -> Option<&mut T> {
self.value.as_mut()
}
pub fn take(&mut self) -> Option<T> {
self.set_time = None;
self.value.take()
}
pub fn is_set(&self) -> bool {
self.value.is_some()
}
pub fn remaining(&self) -> Option<Duration> {
self.set_time.map(|t| {
let elapsed = t.elapsed();
if elapsed < self.duration {
self.duration - elapsed
} else {
Duration::ZERO
}
})
}
pub fn update(&mut self, value: T) {
self.value = Some(value);
}
pub fn reset_timer(&mut self) {
if self.value.is_some() {
self.set_time = Some(Instant::now());
}
}
pub fn auto_clear(&mut self) -> Option<&T> {
if self.is_expired() {
self.clear();
None
} else {
self.value.as_ref()
}
}
}
impl<T> Default for Timeout<T> {
fn default() -> Self {
Self::new(Duration::from_secs(3))
}
}