Skip to main content

timed_debouncer/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(not(test), no_std)]
3
4/// Generic debouncer with internal state.
5#[derive(Debug, Default)]
6pub struct Debouncer<T>
7where
8    T: Default,
9{
10    /// Processed value.
11    value: T,
12
13    /// Tick number of last value change.
14    last_change: Option<u64>,
15}
16
17impl<T> Debouncer<T>
18where
19    T: Default + Copy + PartialEq,
20{
21    /// Returns a new instance.
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Updates the debouncer with a new input value and returns the processed value.
27    /// - `value` is the raw input value to be debounced.
28    /// - `tick` is the current timestamp tick.
29    /// - `freeze_ticks` is the number of ticks for that a value is freezed after a change.
30    pub fn update(&mut self, value: T, tick: u64, freeze_ticks: u32) -> T {
31        if value == self.value {
32            return self.value;
33        }
34
35        match self.last_change {
36            Some(last_change) => {
37                if tick >= last_change + freeze_ticks as u64 {
38                    self.value = value;
39                    self.last_change = Some(tick);
40                }
41            }
42            None => {
43                // At first value change, use input value without any further checks.
44                self.value = value;
45                self.last_change = Some(tick);
46            }
47        }
48
49        self.value
50    }
51
52    /// Returns the last processed value.
53    pub fn value(&self) -> T {
54        self.value
55    }
56
57    /// Sets a new value as processed value.
58    pub fn set_value(&mut self, value: T) {
59        self.value = value;
60    }
61
62    /// Returns the tick number of last value change or `None` if the value hasn't changed yet.
63    pub fn last_change(&self) -> Option<u64> {
64        self.last_change
65    }
66}
67
68#[cfg(test)]
69mod tests;