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;