1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Created on Thu Aug 10 2023
 *
 * Copyright (c) storycraft. Licensed under the MIT Licence.
 */

#![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]
/// Higher kinded type helper for [`struct@EventSource`]
macro_rules! EventSource {
    ($($ty: tt)*) => {
        $crate::EventSource<$crate::__private::ForLt!($($ty)*)>
    };
}

#[macro_export]
/// Emit event. As methods can't do mutable reborrowing correctly, you should use this macro.
macro_rules! emit {
    ($source: expr, $event: expr) => {
        $source.with_emitter(|mut emitter| while emitter.emit_next($event).is_some() {});
    };
}

/// Event source
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> {
    /// Create new [`struct@EventSource`]
    pub const fn new() -> Self {
        Self {
            // SAFETY: There is only one variant of [`Pinlist`]
            list: Mutex::new(PinList::new(unsafe { Unchecked::new() })),
        }
    }

    /// Create [`EventEmitter`] for this [`struct@EventSource`]
    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(),
        });
    }

    /// Listen events
    ///
    /// It can be called after woken if another event occurred before task continue
    pub fn on<F>(&self, listener: F) -> EventFnFuture<F, T>
    where
        F: FnMut(T::Of<'_>, &mut ControlFlow) + Send + Sync,
    {
        EventFnFuture::new(self, listener)
    }

    /// Listen event until listener returns [`Option::Some`]
    ///
    /// Unlike [`EventSource::on`] it will ignore every events once listener is done or returns with [`Option::Some`].
    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
    }
}

/// Struct for emitting values for each listeners
#[derive(Debug)]
pub struct EventEmitter<'a, T: ForLifetime> {
    cursor: CursorMut<'a, NodeTypes<T>>,
}

impl<T: ForLifetime> EventEmitter<'_, T> {
    /// Emit event to next listener
    pub fn emit_next(&mut self, event: T::Of<'_>) -> Option<()> {
        let node = self.cursor.protected_mut()?;

        // SAFETY: Listener closure pointer is valid
        if unsafe { !node.poll(event) } {
            return None;
        }

        self.cursor.move_next();

        Some(())
    }
}