event_source/
lib.rs

1/*
2 * Created on Thu Aug 10 2023
3 *
4 * Copyright (c) storycraft. Licensed under the MIT Licence.
5 */
6
7#![no_std]
8#![doc = include_str!("../README.md")]
9
10#[doc(hidden)]
11pub mod __private;
12mod future;
13mod sealed;
14mod types;
15
16pub use future::{ControlFlow, EventFnFuture};
17
18use core::fmt::{self, Debug};
19
20use higher_kinded_types::ForLifetime;
21use parking_lot::Mutex;
22
23use pin_list::{id::Unchecked, CursorMut};
24
25use types::{NodeTypes, PinList};
26
27#[macro_export]
28/// Higher kinded type helper for [`struct@EventSource`]
29macro_rules! EventSource {
30    ($($ty: tt)*) => {
31        $crate::EventSource<$crate::__private::ForLt!($($ty)*)>
32    };
33}
34
35#[macro_export]
36/// Emit event. As methods can't do mutable reborrowing correctly, you should use this macro.
37macro_rules! emit {
38    ($source: expr, $event: expr) => {
39        $source.with_emitter(|mut emitter| while emitter.emit_next($event).is_some() {});
40    };
41}
42
43/// Event source
44pub struct EventSource<T: ForLifetime> {
45    list: Mutex<PinList<T>>,
46}
47
48impl<T: ForLifetime> Debug for EventSource<T> {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        f.debug_struct("EventSource")
51            .field("list", &self.list)
52            .finish()
53    }
54}
55
56impl<T: ForLifetime> EventSource<T> {
57    /// Create new [`struct@EventSource`]
58    pub const fn new() -> Self {
59        Self {
60            // SAFETY: There is only one variant of [`Pinlist`]
61            list: Mutex::new(PinList::new(unsafe { Unchecked::new() })),
62        }
63    }
64
65    /// Create [`EventEmitter`] for this [`struct@EventSource`]
66    pub fn with_emitter(&self, emit_fn: impl FnOnce(EventEmitter<T>)) {
67        let mut list = self.list.lock();
68
69        emit_fn(EventEmitter {
70            cursor: list.cursor_front_mut(),
71        });
72    }
73
74    /// Listen events
75    ///
76    /// It can be called after woken if another event occurred before task continue
77    pub fn on<F>(&self, listener: F) -> EventFnFuture<F, T>
78    where
79        F: FnMut(T::Of<'_>, &mut ControlFlow) + Send,
80    {
81        EventFnFuture::new(self, listener)
82    }
83
84    /// Listen event until listener returns [`Option::Some`]
85    ///
86    /// Unlike [`EventSource::on`] it will ignore every events once listener is done or returns with [`Option::Some`].
87    pub async fn once<F, R>(&self, mut listener: F) -> Option<R>
88    where
89        F: FnMut(T::Of<'_>, &mut ControlFlow) -> Option<R> + Send,
90        R: Send,
91    {
92        let mut out = None;
93
94        self.on(|event, flow| {
95            if flow.done() {
96                return;
97            }
98
99            if let output @ Some(_) = listener(event, flow) {
100                out = output;
101                flow.set_done();
102            }
103        })
104        .await;
105
106        out
107    }
108}
109
110/// Struct for emitting values for each listeners
111#[derive(Debug)]
112pub struct EventEmitter<'a, T: ForLifetime> {
113    cursor: CursorMut<'a, NodeTypes<T>>,
114}
115
116impl<T: ForLifetime> EventEmitter<'_, T> {
117    /// Emit event to next listener
118    pub fn emit_next(&mut self, event: T::Of<'_>) -> Option<()> {
119        let node = self.cursor.protected_mut()?;
120
121        // SAFETY: Listener closure pointer is valid
122        if unsafe { !node.poll(event) } {
123            return None;
124        }
125
126        self.cursor.move_next();
127
128        Some(())
129    }
130}