#![no_std]
#![doc = include_str!("../README.md")]
#[doc(hidden)]
pub mod __private;
mod future;
mod sealed;
mod types;
pub use future::{ControlFlow, EventFnFuture};
use core::fmt::{self, Debug};
use higher_kinded_types::ForLifetime;
use parking_lot::Mutex;
use pin_list::{id::Unchecked, CursorMut};
use types::{NodeTypes, PinList};
#[macro_export]
macro_rules! EventSource {
($($ty: tt)*) => {
$crate::EventSource<$crate::__private::ForLt!($($ty)*)>
};
}
#[macro_export]
macro_rules! emit {
($source: expr, $event: expr) => {
$source.with_emitter(|mut emitter| while emitter.emit_next($event).is_some() {});
};
}
pub struct EventSource<T: ForLifetime> {
list: Mutex<PinList<T>>,
}
impl<T: ForLifetime> Debug for EventSource<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventSource")
.field("list", &self.list)
.finish()
}
}
impl<T: ForLifetime> EventSource<T> {
pub const fn new() -> Self {
Self {
list: Mutex::new(PinList::new(unsafe { Unchecked::new() })),
}
}
pub fn with_emitter(&self, emit_fn: impl FnOnce(EventEmitter<T>)) {
let mut list = self.list.lock();
emit_fn(EventEmitter {
cursor: list.cursor_front_mut(),
});
}
pub fn on<F>(&self, listener: F) -> EventFnFuture<F, T>
where
F: FnMut(T::Of<'_>, &mut ControlFlow) + Send + Sync,
{
EventFnFuture::new(self, listener)
}
pub async fn once<F, R>(&self, mut listener: F) -> Option<R>
where
F: FnMut(T::Of<'_>, &mut ControlFlow) -> Option<R> + Send + Sync,
R: Send + Sync,
{
let mut out = None;
self.on(|event, flow| {
if flow.done() {
return;
}
if let output @ Some(_) = listener(event, flow) {
out = output;
flow.set_done();
}
})
.await;
out
}
}
#[derive(Debug)]
pub struct EventEmitter<'a, T: ForLifetime> {
cursor: CursorMut<'a, NodeTypes<T>>,
}
impl<T: ForLifetime> EventEmitter<'_, T> {
pub fn emit_next(&mut self, event: T::Of<'_>) -> Option<()> {
let node = self.cursor.protected_mut()?;
if unsafe { !node.poll(event) } {
return None;
}
self.cursor.move_next();
Some(())
}
}