#![allow(dead_code)]
#[derive(Debug, Clone)]
pub struct DebouncerConfig {
pub quiet_period: u64,
}
#[derive(Debug, Clone)]
pub struct EventDebouncer {
config: DebouncerConfig,
last_trigger_time: u64,
current_time: u64,
pending: bool,
fired: bool,
fire_count: u64,
}
#[allow(dead_code)]
pub fn default_debouncer_config() -> DebouncerConfig {
DebouncerConfig { quiet_period: 5 }
}
#[allow(dead_code)]
pub fn new_event_debouncer(config: DebouncerConfig) -> EventDebouncer {
EventDebouncer {
config,
last_trigger_time: 0,
current_time: 0,
pending: false,
fired: false,
fire_count: 0,
}
}
#[allow(dead_code)]
pub fn debouncer_trigger(deb: &mut EventDebouncer) {
deb.last_trigger_time = deb.current_time;
deb.pending = true;
deb.fired = false;
}
#[allow(dead_code)]
pub fn debouncer_tick(deb: &mut EventDebouncer) -> bool {
deb.current_time += 1;
deb.fired = false;
if deb.pending && deb.current_time.saturating_sub(deb.last_trigger_time) >= deb.config.quiet_period {
deb.pending = false;
deb.fired = true;
deb.fire_count += 1;
}
deb.fired
}
#[allow(dead_code)]
pub fn debouncer_is_pending(deb: &EventDebouncer) -> bool {
deb.pending
}
#[allow(dead_code)]
pub fn debouncer_is_fired(deb: &EventDebouncer) -> bool {
deb.fired
}
#[allow(dead_code)]
pub fn debouncer_reset(deb: &mut EventDebouncer) {
deb.last_trigger_time = 0;
deb.current_time = 0;
deb.pending = false;
deb.fired = false;
deb.fire_count = 0;
}
#[allow(dead_code)]
pub fn debouncer_last_trigger_time(deb: &EventDebouncer) -> u64 {
deb.last_trigger_time
}
#[allow(dead_code)]
pub fn debouncer_to_json(deb: &EventDebouncer) -> String {
format!(
"{{\"quiet_period\":{},\"current_time\":{},\"pending\":{},\"fired\":{},\"fire_count\":{}}}",
deb.config.quiet_period,
deb.current_time,
deb.pending,
deb.fired,
deb.fire_count
)
}
#[allow(dead_code)]
pub fn debouncer_fire_count(deb: &EventDebouncer) -> u64 {
deb.fire_count
}
#[cfg(test)]
mod tests {
use super::*;
fn make_deb(quiet: u64) -> EventDebouncer {
new_event_debouncer(DebouncerConfig { quiet_period: quiet })
}
#[test]
fn test_initial_not_pending() {
let deb = make_deb(3);
assert!(!debouncer_is_pending(&deb));
assert!(!debouncer_is_fired(&deb));
}
#[test]
fn test_trigger_sets_pending() {
let mut deb = make_deb(3);
debouncer_trigger(&mut deb);
assert!(debouncer_is_pending(&deb));
}
#[test]
fn test_fires_after_quiet_period() {
let mut deb = make_deb(3);
debouncer_trigger(&mut deb);
debouncer_tick(&mut deb); debouncer_tick(&mut deb); assert!(!debouncer_is_fired(&deb));
let fired = debouncer_tick(&mut deb); assert!(fired);
assert!(debouncer_is_fired(&deb));
}
#[test]
fn test_retriggering_resets_quiet_period() {
let mut deb = make_deb(3);
debouncer_trigger(&mut deb); debouncer_tick(&mut deb); debouncer_trigger(&mut deb); debouncer_tick(&mut deb); debouncer_tick(&mut deb); assert!(!debouncer_is_fired(&deb));
debouncer_tick(&mut deb); assert!(debouncer_is_fired(&deb));
}
#[test]
fn test_fire_count_increments() {
let mut deb = make_deb(2);
debouncer_trigger(&mut deb);
debouncer_tick(&mut deb);
debouncer_tick(&mut deb); assert_eq!(debouncer_fire_count(&deb), 1);
debouncer_trigger(&mut deb);
debouncer_tick(&mut deb);
debouncer_tick(&mut deb); assert_eq!(debouncer_fire_count(&deb), 2);
}
#[test]
fn test_not_fired_without_trigger() {
let mut deb = make_deb(1);
debouncer_tick(&mut deb);
debouncer_tick(&mut deb);
assert!(!debouncer_is_fired(&deb));
assert_eq!(debouncer_fire_count(&deb), 0);
}
#[test]
fn test_reset() {
let mut deb = make_deb(2);
debouncer_trigger(&mut deb);
debouncer_tick(&mut deb);
debouncer_reset(&mut deb);
assert!(!debouncer_is_pending(&deb));
assert_eq!(debouncer_fire_count(&deb), 0);
assert_eq!(deb.current_time, 0);
}
#[test]
fn test_last_trigger_time() {
let mut deb = make_deb(5);
debouncer_tick(&mut deb); debouncer_tick(&mut deb); debouncer_trigger(&mut deb);
assert_eq!(debouncer_last_trigger_time(&deb), 2);
}
#[test]
fn test_to_json_contains_quiet_period() {
let deb = make_deb(7);
let json = debouncer_to_json(&deb);
assert!(json.contains("\"quiet_period\":7"));
}
#[test]
fn test_fired_clears_next_tick() {
let mut deb = make_deb(1);
debouncer_trigger(&mut deb);
debouncer_tick(&mut deb); assert!(debouncer_is_fired(&deb));
debouncer_tick(&mut deb); assert!(!debouncer_is_fired(&deb));
}
}