mrogalski_looper/
lib.rs

1//! Clean abstraction for a single-threaded event loop. Built as a lightweight wrapper around the `std::sync::mpsc` package.
2//!
3//! # Example usage:
4//!
5//! ```rust
6//! use mrogalski_looper::{Handler, Sender, run};
7//!
8//! struct ExampleHandler {
9//!     data: Vec<i32>,
10//! }
11//!
12//! impl Handler<i32> for ExampleHandler {
13//!
14//!     // Invoked right after the `run` function is called.
15//!     fn start(&mut self, sender: Sender<i32>) {
16//!         for elem in vec![1, 2, 3] {
17//!             sender.send(elem.clone()).unwrap();
18//!         }
19//!     }
20//!
21//!     // Called for every `event` sent to the `sender`.
22//!     fn handle(&mut self, i: i32) -> bool {
23//!         self.data.push(i);
24//!         true
25//!     }
26//!
27//!     // Called after last event is processed or an error occurs.
28//!     fn end(self) {
29//!         assert_eq!(self.data, vec![1, 2, 3]);
30//!     }
31//! }
32//!
33//! // Blocks the current thread until all events are processed.
34//! run(ExampleHandler { data: vec![] });
35//!
36//! ```
37
38#[doc(no_inline)]
39pub use std::sync::mpsc::Sender;
40
41#[cfg(test)]
42mod tests;
43
44/// Handles events sent to the event loop.
45pub trait Handler<EVENT: Send>: Sized {
46    /// Called immediately after starting the event loop.
47    ///
48    /// The `Sender` argument can be used to send new events. It can be cloned and passed to other threads in this method.
49    ///
50    /// When the last sender is dropped and there are no events pending, the event loop terminates.
51    fn start(&mut self, sender: Sender<EVENT>);
52
53    /// Called for every event sent to the event loop.
54    fn handle(&mut self, event: EVENT) -> bool;
55
56    /// Called after event loop terminates.
57    ///
58    /// The default implementation does nothing and can be overriden.
59    fn end(self) {}
60}
61
62/// Runs the event loop on the current thread.
63pub fn run<EVENT: Send, HANDLER: Handler<EVENT>>(mut handler: HANDLER) {
64    let (tx, rx) = std::sync::mpsc::channel();
65    handler.start(tx);
66    let mut running = true;
67    while running {
68        running = match rx.recv() {
69            Ok(event) => handler.handle(event),
70            _ => false,
71        }
72    }
73    handler.end();
74}