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
//! # Events specification.

use anyhow::Result;
use tokio::sync::Mutex;

pub(crate) mod chatlist_events;
mod payload;

pub use self::payload::EventType;

/// Event channel.
#[derive(Debug, Clone)]
pub struct Events {
    /// Unused receiver to prevent the channel from closing.
    _receiver: async_broadcast::InactiveReceiver<Event>,

    /// Sender side of the event channel.
    sender: async_broadcast::Sender<Event>,
}

impl Default for Events {
    fn default() -> Self {
        Self::new()
    }
}

impl Events {
    /// Creates a new event channel.
    pub fn new() -> Self {
        let (mut sender, _receiver) = async_broadcast::broadcast(1_000);

        // We only keep this receiver around
        // to prevent the channel from closing.
        // Deactivating it to prevent it from consuming memory
        // holding events that are not going to be received.
        let _receiver = _receiver.deactivate();

        // Remove oldest event on overflow.
        sender.set_overflow(true);

        Self { _receiver, sender }
    }

    /// Emits an event into event channel.
    ///
    /// If the channel is full, deletes the oldest event first.
    pub fn emit(&self, event: Event) {
        self.sender.try_broadcast(event).ok();
    }

    /// Creates an event emitter.
    pub fn get_emitter(&self) -> EventEmitter {
        EventEmitter(Mutex::new(self.sender.new_receiver()))
    }
}

/// A receiver of events from a [`Context`].
///
/// See [`Context::get_event_emitter`] to create an instance.  If multiple instances are
/// created events emitted by the [`Context`] will only be delivered to one of the
/// `EventEmitter`s.
///
/// [`Context`]: crate::context::Context
/// [`Context::get_event_emitter`]: crate::context::Context::get_event_emitter
#[derive(Debug)]
pub struct EventEmitter(Mutex<async_broadcast::Receiver<Event>>);

impl EventEmitter {
    /// Async recv of an event. Return `None` if the `Sender` has been dropped.
    ///
    /// [`try_recv`]: Self::try_recv
    pub async fn recv(&self) -> Option<Event> {
        let mut lock = self.0.lock().await;
        lock.recv().await.ok()
    }

    /// Tries to receive an event without blocking.
    ///
    /// Returns error if no events are available for reception
    /// or if receiver mutex is locked by a concurrent call to [`recv`]
    /// or `try_recv`.
    ///
    /// [`recv`]: Self::recv
    pub fn try_recv(&self) -> Result<Event> {
        // Using `try_lock` instead of `lock`
        // to avoid blocking
        // in case there is a concurrent call to `recv`.
        let mut lock = self.0.try_lock()?;
        let event = lock.try_recv()?;
        Ok(event)
    }
}

/// The event emitted by a [`Context`] from an [`EventEmitter`].
///
/// Events are documented on the C/FFI API in `deltachat.h` as `DC_EVENT_*` constants.  The
/// context emits them in relation to various operations happening, a lot of these are again
/// documented in `deltachat.h`.
///
/// [`Context`]: crate::context::Context
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Event {
    /// The ID of the [`Context`] which emitted this event.
    ///
    /// This allows using multiple [`Context`]s in a single process as they are identified
    /// by this ID.
    ///
    /// [`Context`]: crate::context::Context
    pub id: u32,
    /// The event payload.
    ///
    /// These are documented in `deltachat.h` as the `DC_EVENT_*` constants.
    pub typ: EventType,
}