1use crate::events::io::{InputEvents, InputEventsIter};
2use std::ops::Bound;
3
4#[derive(Copy, Clone, Debug)]
5enum State {
6 Started {
7 first_event_sample_time: Option<u32>,
8 },
9 HasNextEvent {
10 next_event_index: u32,
11 next_event_sample_time: u32,
12 },
13 Ended,
14}
15
16#[derive(Clone)]
20#[must_use = "iterators are lazy and do nothing unless consumed"]
21pub struct EventBatcher<'a> {
22 events: &'a InputEvents<'a>,
23 events_len: u32,
24 state: State,
25}
26
27impl<'a> EventBatcher<'a> {
28 pub(crate) fn new(events: &'a InputEvents<'a>) -> Self {
29 let events_len = events.len();
30
31 Self {
32 events,
33 events_len,
34 state: State::Started {
35 first_event_sample_time: if events_len == 0 {
36 None
37 } else {
38 events.get(0).map(|e| e.header().time())
39 },
40 },
41 }
42 }
43
44 fn next_non_matching(
45 &self,
46 current_event_index: u32,
47 current_sample: u32,
48 ) -> Option<(u32, u32)> {
49 for next_index in (current_event_index + 1)..self.events_len {
50 let Some(next_event) = self.events.get(next_index) else {
51 continue;
52 };
53
54 let next_event_sample_time = next_event.header().time();
55 if next_event_sample_time != current_sample {
56 return Some((next_index, next_event_sample_time));
57 }
58 }
59
60 None
61 }
62}
63
64impl<'a> Iterator for EventBatcher<'a> {
65 type Item = EventBatch<'a>;
66
67 fn next(&mut self) -> Option<Self::Item> {
68 use crate::events::io::batcher::State::*;
69
70 let (current_event_index, current_sample, next_non_matching_event) = match self.state {
71 Ended => return None,
72 HasNextEvent {
73 next_event_index,
74 next_event_sample_time,
75 } => (
76 next_event_index,
77 next_event_sample_time,
78 self.next_non_matching(next_event_index, next_event_sample_time),
79 ),
80 Started {
81 first_event_sample_time: Some(0),
82 } => (0, 0, self.next_non_matching(0, 0)),
83 Started {
84 first_event_sample_time: None,
85 } => (0, 0, None),
86 Started {
87 first_event_sample_time: Some(first_event_sample_time),
88 } => (0, 0, Some((0, first_event_sample_time))),
89 };
90
91 match next_non_matching_event {
92 None => {
93 self.state = Ended;
94
95 Some(EventBatch {
96 events: InputEventsIter::new(self.events, current_event_index..self.events_len),
97 first_sample: current_sample as usize,
98 next_batch_first_sample: None,
99 })
100 }
101 Some((next_event_index, next_event_sample_time)) => {
102 self.state = HasNextEvent {
103 next_event_sample_time,
104 next_event_index,
105 };
106
107 Some(EventBatch {
108 events: InputEventsIter::new(
109 self.events,
110 current_event_index..next_event_index,
111 ),
112 first_sample: current_sample as usize,
113 next_batch_first_sample: Some(next_event_sample_time as usize),
114 })
115 }
116 }
117 }
118}
119
120pub struct EventBatch<'a> {
125 events: InputEventsIter<'a>,
126 first_sample: usize,
127 next_batch_first_sample: Option<usize>,
128}
129
130impl<'a> EventBatch<'a> {
131 #[inline]
133 pub fn events(&self) -> InputEventsIter<'a> {
134 self.events.clone()
135 }
136
137 #[inline]
141 pub fn first_sample(&self) -> usize {
142 self.first_sample
143 }
144
145 #[inline]
152 pub fn next_batch_first_sample(&self) -> Option<usize> {
153 self.next_batch_first_sample
154 }
155
156 #[inline]
186 pub fn sample_bounds(&self) -> (Bound<usize>, Bound<usize>) {
187 (
188 Bound::Included(self.first_sample),
189 match self.next_batch_first_sample {
190 None => Bound::Unbounded,
191 Some(end) => Bound::Excluded(end),
192 },
193 )
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200 use crate::events::event_types::ParamGestureBeginEvent;
201 use crate::utils::ClapId;
202
203 const PARAM: ClapId = ClapId::new(0);
204
205 #[test]
206 pub fn works_with_empty_events() {
207 let events = InputEvents::empty();
208 let mut events = events.batch();
209
210 {
211 let batch = events.next().unwrap();
212 assert_eq!(batch.first_sample(), 0);
213 assert_eq!(batch.next_batch_first_sample(), None);
214
215 let mut batch_events = batch.events();
216 assert!(batch_events.next().is_none());
217 }
218
219 assert!(events.next().is_none())
220 }
221
222 #[test]
223 pub fn works_with_single_zero_event() {
224 let buf = [ParamGestureBeginEvent::new(0, PARAM)];
225
226 let events = InputEvents::from_buffer(&buf);
227 let mut events = events.batch();
228
229 {
230 let batch = events.next().unwrap();
231 assert_eq!(batch.first_sample(), 0);
232 assert_eq!(batch.next_batch_first_sample(), None);
233
234 let mut batch_events = batch.events();
235 assert_eq!(&buf[0], batch_events.next().unwrap().as_event().unwrap());
236 assert!(batch_events.next().is_none());
237 }
238
239 assert!(events.next().is_none())
240 }
241
242 #[test]
243 pub fn works_with_single_nonzero_event() {
244 let buf = [ParamGestureBeginEvent::new(5, PARAM)];
245
246 let events = InputEvents::from_buffer(&buf);
247 let mut events = events.batch();
248
249 {
250 let batch = events.next().unwrap();
251 assert_eq!(batch.first_sample(), 0);
252 assert_eq!(batch.next_batch_first_sample(), Some(5));
253
254 let mut batch_events = batch.events();
255 assert!(batch_events.next().is_none());
256 }
257 {
258 let batch = events.next().unwrap();
259 assert_eq!(batch.first_sample(), 5);
260 assert_eq!(batch.next_batch_first_sample(), None);
261
262 let mut batch_events = batch.events();
263 assert_eq!(&buf[0], batch_events.next().unwrap().as_event().unwrap());
264 assert!(batch_events.next().is_none());
265 }
266
267 assert!(events.next().is_none())
268 }
269
270 #[test]
271 pub fn works_with_two_grouped_nonzero_events() {
272 let buf = [
273 ParamGestureBeginEvent::new(5, PARAM),
274 ParamGestureBeginEvent::new(5, PARAM),
275 ];
276
277 let events = InputEvents::from_buffer(&buf);
278 let mut events = events.batch();
279
280 {
281 let batch = events.next().unwrap();
282 assert_eq!(batch.first_sample(), 0);
283 assert_eq!(batch.next_batch_first_sample(), Some(5));
284
285 let mut batch_events = batch.events();
286 assert!(batch_events.next().is_none());
287 }
288 {
289 let batch = events.next().unwrap();
290 assert_eq!(batch.first_sample(), 5);
291 assert_eq!(batch.next_batch_first_sample(), None);
292
293 let mut batch_events = batch.events();
294 assert_eq!(&buf[0], batch_events.next().unwrap().as_event().unwrap());
295 assert_eq!(&buf[1], batch_events.next().unwrap().as_event().unwrap());
296 assert!(batch_events.next().is_none());
297 }
298
299 assert!(events.next().is_none())
300 }
301
302 #[test]
303 pub fn works_with_two_distinct_nonzero_events() {
304 let buf = [
305 ParamGestureBeginEvent::new(5, PARAM),
306 ParamGestureBeginEvent::new(10, PARAM),
307 ];
308
309 let events = InputEvents::from_buffer(&buf);
310 let mut events = events.batch();
311
312 {
313 let batch = events.next().unwrap();
314 assert_eq!(batch.first_sample(), 0);
315 assert_eq!(batch.next_batch_first_sample(), Some(5));
316
317 let mut batch_events = batch.events();
318 assert!(batch_events.next().is_none());
319 }
320 {
321 let batch = events.next().unwrap();
322 assert_eq!(batch.first_sample(), 5);
323 assert_eq!(batch.next_batch_first_sample(), Some(10));
324
325 let mut batch_events = batch.events();
326 assert_eq!(&buf[0], batch_events.next().unwrap().as_event().unwrap());
327 assert!(batch_events.next().is_none());
328 }
329 {
330 let batch = events.next().unwrap();
331 assert_eq!(batch.first_sample(), 10);
332 assert_eq!(batch.next_batch_first_sample(), None);
333
334 let mut batch_events = batch.events();
335 assert_eq!(&buf[1], batch_events.next().unwrap().as_event().unwrap());
336 assert!(batch_events.next().is_none());
337 }
338
339 assert!(events.next().is_none())
340 }
341
342 #[test]
343 pub fn three_distinct_nonzero_events() {
344 let buf = [
345 ParamGestureBeginEvent::new(5, PARAM),
346 ParamGestureBeginEvent::new(10, PARAM),
347 ParamGestureBeginEvent::new(15, PARAM),
348 ];
349
350 let events = InputEvents::from_buffer(&buf);
351 let mut events = events.batch();
352
353 {
354 let batch = events.next().unwrap();
355 assert_eq!(batch.first_sample(), 0);
356 assert_eq!(batch.next_batch_first_sample(), Some(5));
357
358 let mut batch_events = batch.events();
359 assert!(batch_events.next().is_none());
360 }
361 {
362 let batch = events.next().unwrap();
363 assert_eq!(batch.first_sample(), 5);
364 assert_eq!(batch.next_batch_first_sample(), Some(10));
365
366 let mut batch_events = batch.events();
367 assert_eq!(&buf[0], batch_events.next().unwrap().as_event().unwrap());
368 assert!(batch_events.next().is_none());
369 }
370 {
371 let batch = events.next().unwrap();
372 assert_eq!(batch.first_sample(), 10);
373 assert_eq!(batch.next_batch_first_sample(), Some(15));
374
375 let mut batch_events = batch.events();
376 assert_eq!(&buf[1], batch_events.next().unwrap().as_event().unwrap());
377 assert!(batch_events.next().is_none());
378 }
379 {
380 let batch = events.next().unwrap();
381 assert_eq!(batch.first_sample(), 15);
382 assert_eq!(batch.next_batch_first_sample(), None);
383
384 let mut batch_events = batch.events();
385 assert_eq!(&buf[2], batch_events.next().unwrap().as_event().unwrap());
386 assert!(batch_events.next().is_none());
387 }
388
389 assert!(events.next().is_none())
390 }
391}