gled-core 2.34.0

The engine of gled without a user interface: inputs, timing, rendering, Art-Net/DMX output and storage
Documentation
//! Events of the last ticks, numbered, so an interface that is sent updates
//! less often than the engine ticks still sees every event: input events
//! for assigning inputs, MIDI traffic for the monitor and MIDI learn.

use std::collections::VecDeque;

use gled_protocol::midi::MidiMonitorEvent;

use crate::input::event::InputEvent;

pub(crate) type InputLog = EventLog<InputEvent>;
pub(crate) type MidiLog = EventLog<MidiMonitorEvent>;
pub(crate) type LearnLog = EventLog<[u8; 3]>;

/// How many events are kept for interfaces that lag behind.
const KEPT: usize = 64;

#[derive(Debug, Clone)]
pub(crate) struct EventLog<T> {
    /// The number the next event gets.
    next: u64,
    events: VecDeque<(u64, T)>,
}

impl<T> Default for EventLog<T> {
    fn default() -> Self {
        Self {
            next: 0,
            events: VecDeque::new(),
        }
    }
}

impl<T: Clone> EventLog<T> {
    pub(crate) fn push(&mut self, event: T) {
        self.events.push_back((self.next, event));
        self.next += 1;
        while self.events.len() > KEPT {
            self.events.pop_front();
        }
    }

    /// The number the next event will get.
    pub(crate) fn next(&self) -> u64 {
        self.next
    }

    /// The events numbered `from` and later.
    pub(crate) fn since(&self, from: u64) -> Vec<T> {
        self.events
            .iter()
            .filter(|(number, _)| *number >= from)
            .map(|(_, event)| event.clone())
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::input::key_code::KeyCode;

    #[test]
    fn keeps_the_newest_events_by_number() {
        let mut log = InputLog::default();
        for _ in 0..(KEPT + 6) {
            log.push(InputEvent::Key(KeyCode::A));
        }
        log.push(InputEvent::Key(KeyCode::B));
        assert_eq!(log.next(), KEPT as u64 + 7);
        assert_eq!(log.since(log.next() - 1), vec![InputEvent::Key(KeyCode::B)]);
        assert_eq!(log.since(0).len(), KEPT);
    }
}