1mod nexus;
20
21#[cfg(feature = "arc")]
22pub mod arc;
23
24#[cfg(feature = "extras")]
25pub mod extras;
26
27#[cfg(feature = "rtapi")]
28pub mod rtapi;
29
30use super::EventApi;
31use crate::{revertible::Revertible, util::str_to_c, AddonApi};
32use std::{
33 ffi::{c_char, c_void},
34 marker::PhantomData,
35 mem,
36};
37
38pub use self::nexus::*;
39
40#[derive(Debug, Clone, Copy)]
42pub struct Event<T> {
43 pub identifier: &'static str,
44 _phantom: PhantomData<T>,
45}
46
47impl<T> Event<T> {
48 #[inline]
53 pub const unsafe fn new(identifier: &'static str) -> Self {
54 Self {
55 identifier,
56 _phantom: PhantomData,
57 }
58 }
59
60 #[inline]
62 pub fn subscribe(
63 &self,
64 callback: RawEventConsume<T>,
65 ) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
66 unsafe { event_subscribe_typed(self.identifier, callback) }
67 }
68
69 #[inline]
71 pub fn raise(&self, event_data: &T) {
72 unsafe { event_raise(self.identifier, event_data) }
73 }
74}
75
76pub type RawEventConsume<T> = extern "C-unwind" fn(event_args: *const T);
77
78pub type RawEventConsumeUnknown = RawEventConsume<c_void>;
79
80pub type RawEventRaise =
81 unsafe extern "C-unwind" fn(identifier: *const c_char, event_data: *const c_void);
82
83pub type RawEventRaiseNotification = unsafe extern "C-unwind" fn(identifier: *const c_char);
84
85pub type RawEventRaiseTargeted = unsafe extern "C-unwind" fn(
86 signature: i32,
87 identifier: *const c_char,
88 event_data: *const c_void,
89);
90
91pub type RawEventRaiseNotificationTargeted =
92 unsafe extern "C-unwind" fn(signature: i32, identifier: *const c_char);
93
94pub type RawEventSubscribe = unsafe extern "C-unwind" fn(
95 identifier: *const c_char,
96 consume_callback: RawEventConsumeUnknown,
97);
98
99pub fn event_subscribe_unknown(
103 identifier: impl AsRef<str>,
104 callback: RawEventConsumeUnknown,
105) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
106 let identifier = str_to_c(identifier, "failed to convert event identifier");
107 let EventApi {
108 subscribe,
109 unsubscribe,
110 ..
111 } = AddonApi::get().event;
112 unsafe { subscribe(identifier.as_ptr(), callback) };
113 let revert = move || unsafe { unsubscribe(identifier.as_ptr(), callback) };
114 revert.into()
115}
116
117pub unsafe fn event_subscribe_typed<T>(
124 identifier: impl AsRef<str>,
125 callback: RawEventConsume<T>,
126) -> Revertible<impl Fn() + Send + Sync + Clone + 'static> {
127 let callback =
128 unsafe { mem::transmute::<RawEventConsume<T>, RawEventConsumeUnknown>(callback) };
129 event_subscribe_unknown(identifier, callback)
130}
131
132pub fn event_unsubscribe(identifier: impl AsRef<str>, callback: RawEventConsumeUnknown) {
134 let identifier = str_to_c(identifier, "failed to convert event identifier");
135 let EventApi { unsubscribe, .. } = AddonApi::get().event;
136 unsafe { unsubscribe(identifier.as_ptr(), callback) }
137}
138
139#[macro_export]
180macro_rules! event_consume {
181 ( < $ty:ty > $callback:expr $(,)? ) => {{
182 const __CALLBACK: fn(::std::option::Option<&$ty>) = ($callback);
183
184 extern "C-unwind" fn __event_callback_wrapper(data: *const $ty) {
185 let _ = unsafe { ::std::mem::transmute::<*const $ty, *const ::std::ffi::c_void>(data) }; __CALLBACK(unsafe { data.as_ref() })
187 }
188
189 __event_callback_wrapper
190 }};
191 ( $ty:ty , $callback:expr $(,)? ) => {
192 $crate::event::event_consume!(<$ty> $callback)
193 };
194 ( | $arg:ident : Option<& $ty:ty > | $body:expr $(,)? ) => {
195 $crate::event::event_consume!(<$ty> |$arg: Option<& $ty >| $body)
196 };
197 ( $callback:expr $(,)? ) => {{
198 $crate::event::event_consume!(<()> $callback)
199 }};
200}
201
202pub use event_consume;
203
204#[macro_export]
257macro_rules! event_subscribe {
258 ( unsafe $event:expr , $ty:ty , $callback:expr $(,)? ) => {
259 unsafe { $crate::event::event_subscribe!($event => $ty, $callback) }
260 };
261 ( unsafe $event:expr => $ty:ty , $callback:expr $(,)? ) => {
262 unsafe { $crate::event::event_subscribe!($event => $ty, $callback) }
263 };
264 ( $event:expr , $ty:ty , $callback:expr $(,)? ) => {
265 $crate::event::event_subscribe!($event => $ty, $callback)
266 };
267 ( $event:expr => $ty:ty , $callback:expr $(,)? ) => {
268 $crate::event::event_subscribe_typed($event, $crate::event::event_consume!(<$ty> $callback))
269 };
270}
271
272pub use event_subscribe;
273
274pub unsafe fn event_raise<T>(identifier: impl AsRef<str>, event_data: &T) {
279 let identifier = str_to_c(identifier, "failed to convert event identifier");
280 let data: *const _ = event_data;
281 let EventApi { raise, .. } = AddonApi::get().event;
282 unsafe { raise(identifier.as_ptr(), data.cast()) }
283}
284
285pub fn event_raise_notification(identifier: impl AsRef<str>) {
287 let identifier = str_to_c(identifier, "failed to convert event identifier");
288 let EventApi {
289 raise_notification, ..
290 } = AddonApi::get().event;
291 unsafe { raise_notification(identifier.as_ptr()) }
292}
293
294pub unsafe fn event_raise_targeted<T>(signature: i32, identifier: impl AsRef<str>, event_data: &T) {
299 let identifier = str_to_c(identifier, "failed to convert event identifier");
300 let data: *const _ = event_data;
301 let EventApi { raise_targeted, .. } = AddonApi::get().event;
302 unsafe { raise_targeted(signature, identifier.as_ptr(), data.cast()) }
303}
304
305pub fn event_raise_notification_targeted(signature: i32, identifier: impl AsRef<str>) {
307 let identifier = str_to_c(identifier, "failed to convert event identifier");
308 let EventApi {
309 raise_notification_targeted,
310 ..
311 } = AddonApi::get().event;
312 unsafe { raise_notification_targeted(signature, identifier.as_ptr()) }
313}