use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct Blink {
pub en: bool,
pub q: bool,
last_toggle: Option<Instant>,
}
impl Blink {
pub fn new() -> Self {
Self {
en: false,
q: false,
last_toggle: None,
}
}
pub fn call(&mut self, en: bool) -> bool {
self.en = en;
if !self.en {
self.q = false;
self.last_toggle = None;
} else {
let now = Instant::now();
match self.last_toggle {
None => {
self.q = true;
self.last_toggle = Some(now);
}
Some(last) => {
if now.duration_since(last) >= Duration::from_millis(500) {
self.q = !self.q;
let expected_next = last + Duration::from_millis(500);
if now.duration_since(expected_next) > Duration::from_millis(500) {
self.last_toggle = Some(now);
} else {
self.last_toggle = Some(expected_next);
}
}
}
}
}
self.q
}
}
impl Default for Blink {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_blink_basic() {
let mut blink = Blink::new();
assert_eq!(blink.call(false), false);
assert_eq!(blink.call(true), true);
std::thread::sleep(Duration::from_millis(50));
assert_eq!(blink.call(true), true);
std::thread::sleep(Duration::from_millis(460));
assert_eq!(blink.call(true), false);
assert_eq!(blink.call(false), false);
assert_eq!(blink.call(true), true);
}
}