dragonfly_plugin/event/
context.rs

1use tokio::sync::mpsc;
2
3use crate::types::{self, PluginToHost};
4
5/// This enum is used internally by `dispatch_event` to
6/// determine what action to take after an event handler runs.
7#[doc(hidden)]
8#[derive(Debug)]
9pub enum EventResult {
10    /// Do nothing, let the default server behavior happen. just sends ack.
11    None,
12    /// Cancel the event, stopping default server behavior.
13    Cancelled,
14    /// Mutate the event, which is sent back to the server.
15    Mutated(types::event_result::Update),
16}
17
18/// A smart wrapper for a server event.
19///
20/// This struct provides read-only access to the event's data
21/// and methods to mutate or cancel it.
22pub struct EventContext<'a, T> {
23    pub data: &'a T,
24    pub result: EventResult,
25
26    event_id: &'a str,
27    sender: mpsc::Sender<PluginToHost>,
28    plugin_id: String,
29    sent: bool,
30}
31
32impl<'a, T> EventContext<'a, T> {
33    #[doc(hidden)]
34    pub fn new(
35        event_id: &'a str,
36        data: &'a T,
37        sender: mpsc::Sender<PluginToHost>,
38        plugin_id: String,
39    ) -> Self {
40        Self {
41            event_id,
42            data,
43            result: EventResult::None,
44            sender,
45            plugin_id,
46            sent: false,
47        }
48    }
49
50    /// Consumes the context and returns the final result.
51    #[doc(hidden)]
52    pub fn into_result(self) -> (String, EventResult) {
53        (self.event_id.to_string(), self.result)
54    }
55
56    /// Cancels the event.
57    ///
58    pub async fn cancel(&mut self) {
59        self.result = EventResult::Cancelled;
60        self.send().await
61    }
62
63    pub(crate) async fn send_ack_if_needed(&mut self) {
64        if self.sent {
65            return;
66        }
67        // result is still EventResultUpdate::None, which sends ack
68        self.send().await;
69    }
70
71    pub async fn send(&mut self) {
72        if self.sent {
73            #[cfg(debug_assertions)]
74            panic!("Attempted to respond twice to the same event!");
75
76            #[cfg(not(debug_assertions))]
77            {
78                eprintln!("Warning: send() called after response already sent");
79                return;
80            }
81        }
82
83        self.sent = true;
84
85        let event_id = self.event_id.to_owned();
86
87        let payload = match &self.result {
88            // If nothing was changed just send ack.
89            EventResult::None => types::EventResult {
90                event_id,
91                cancel: None,
92                update: None,
93            },
94            EventResult::Cancelled => types::EventResult {
95                event_id,
96                cancel: Some(true),
97                update: None,
98            },
99            EventResult::Mutated(update) => types::EventResult {
100                event_id,
101                cancel: None,
102                // TODO: later try to fix this clone.
103                // this gives us best API usage but is memory semantically wrong.
104                // calling this func or like .cancel should consume event.
105                //
106                // but for newbies thats hard to understand.
107                update: Some(update.clone()),
108            },
109        };
110
111        let msg = types::PluginToHost {
112            plugin_id: self.plugin_id.clone(),
113            payload: Some(types::PluginPayload::EventResult(payload)),
114        };
115
116        if let Err(e) = self.sender.send(msg).await {
117            eprintln!("Failed to send event response: {}", e);
118        }
119    }
120}