1use std::cmp::Ordering;
2use std::collections::{BinaryHeap, VecDeque};
3use std::time::{Duration, Instant};
4
5#[derive(Debug, PartialEq, Eq)]
6struct Event<T> {
7 item: T,
8 release_at: Instant,
9}
10
11impl<T: Eq> Ord for Event<T> {
12 fn cmp(&self, other: &Self) -> Ordering {
13 other.release_at.cmp(&self.release_at) }
15}
16
17impl<T: Eq> PartialOrd for Event<T> {
18 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
19 Some(self.cmp(other))
20 }
21}
22
23#[derive(Debug, PartialEq, Eq)]
30pub enum State<T> {
31 Ready(T),
32 Wait(Duration),
33 Empty,
34}
35
36pub trait Get: Sized {
38 type Data;
39
40 fn get(&mut self) -> State<Self::Data>;
43
44 fn iter(&mut self) -> BufferIter<Self> {
48 BufferIter(self)
49 }
50}
51
52pub struct BufferIter<'a, B: Get>(&'a mut B);
55
56impl<'a, B: Get> Iterator for BufferIter<'a, B> {
57 type Item = B::Data;
58
59 fn next(&mut self) -> Option<Self::Item> {
60 match self.0.get() {
61 State::Ready(data) => Some(data),
62 _ => None,
63 }
64 }
65}
66pub struct EventBuffer<T> {
74 delay: Duration,
75 events: VecDeque<Event<T>>,
76}
77
78impl<T: PartialEq> EventBuffer<T> {
79 pub fn new(delay: Duration) -> EventBuffer<T> {
80 EventBuffer {
81 delay,
82 events: VecDeque::new(),
83 }
84 }
85
86 pub fn put(&mut self, item: T) {
87 let time = Instant::now();
88 self.events
89 .retain(|e| e.release_at <= time || e.item != item);
90 self.events.push_back(Event {
91 item,
92 release_at: time + self.delay,
93 });
94 }
95}
96
97impl<T> Get for EventBuffer<T> {
98 type Data = T;
99
100 fn get(&mut self) -> State<T> {
101 let time = Instant::now();
102 match self.events.get(0) {
103 None => State::Empty,
104 Some(e) if e.release_at > time => State::Wait(e.release_at - time),
105 Some(_) => State::Ready(self.events.pop_front().unwrap().item),
106 }
107 }
108}
109
110pub struct MixedEventBuffer<T> {
119 events: BinaryHeap<Event<T>>,
120}
121
122impl<T: Eq> MixedEventBuffer<T> {
123 pub fn new() -> MixedEventBuffer<T> {
124 MixedEventBuffer {
125 events: BinaryHeap::new(),
126 }
127 }
128
129 pub fn put(&mut self, item: T, delay: Duration) {
130 let time = Instant::now();
131 self.events
132 .retain(|e| e.release_at <= time || e.item != item);
133 self.events.push(Event {
134 item,
135 release_at: time + delay,
136 });
137 }
138}
139
140impl<T: Eq> Get for MixedEventBuffer<T> {
141 type Data = T;
142
143 fn get(&mut self) -> State<T> {
144 let time = Instant::now();
145 match self.events.peek() {
146 None => State::Empty,
147 Some(e) if e.release_at > time => State::Wait(e.release_at - time),
148 Some(_) => State::Ready(self.events.pop().unwrap().item),
149 }
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156 use std::thread::sleep;
157 use std::time::Duration;
158
159 mod event_buffer {
160 use super::*;
161
162 #[test]
163 fn wait() {
164 let mut debouncer = EventBuffer::new(Duration::from_millis(20));
165 debouncer.put(1);
166 assert!(matches!(debouncer.get(), State::Wait(_)));
167 sleep(Duration::from_millis(10));
168 assert!(matches!(debouncer.get(), State::Wait(_)));
169 sleep(Duration::from_millis(10));
170 assert!(matches!(debouncer.get(), State::Ready(_)));
171 }
172
173 #[test]
174 fn deduplication() {
175 let mut debouncer = EventBuffer::new(Duration::from_millis(20));
176 debouncer.put(1);
177 debouncer.put(2);
178 sleep(Duration::from_millis(10));
179 debouncer.put(1);
180 sleep(Duration::from_millis(20));
181 assert!(debouncer.iter().eq([2, 1]));
182 }
183 }
184
185 mod mixed_event_buffer {
186 use super::*;
187
188 #[test]
189 fn wait() {
190 let mut debouncer = MixedEventBuffer::new();
191 debouncer.put(1, Duration::from_millis(20));
192 assert!(matches!(debouncer.get(), State::Wait(_)));
193 sleep(Duration::from_millis(10));
194 assert!(matches!(debouncer.get(), State::Wait(_)));
195 sleep(Duration::from_millis(10));
196 assert!(matches!(debouncer.get(), State::Ready(_)));
197 }
198
199 #[test]
200 fn deduplication() {
201 let mut debouncer = MixedEventBuffer::new();
202 debouncer.put(1, Duration::from_millis(20));
203 debouncer.put(2, Duration::from_millis(30));
204 sleep(Duration::from_millis(10));
205 debouncer.put(1, Duration::from_millis(10));
206 sleep(Duration::from_millis(20));
207 assert!(debouncer.iter().eq([1, 2]));
208 }
209
210 #[test]
211 fn event_order() {
212 let mut debouncer = MixedEventBuffer::new();
213 debouncer.put(2, Duration::from_millis(20));
214 debouncer.put(1, Duration::from_millis(10));
215 sleep(Duration::from_millis(30));
216 assert!(debouncer.iter().eq([1, 2]));
217 }
218 }
219}