scarab_plugin_api/events/
registry.rs1use super::{EventArgs, EventHandler, EventResult, EventType, HandlerEntry};
33use std::collections::HashMap;
34use std::sync::atomic::{AtomicU64, Ordering};
35
36#[deprecated(
55 since = "0.1.0",
56 note = "Use Bevy ECS events (scarab-client/src/events/bevy_events.rs) instead of Arc<Mutex<EventRegistry>>. \
57 See crates/scarab-plugin-api/src/events/registry.rs module docs for migration guide."
58)]
59pub struct EventRegistry {
60 handlers: HashMap<EventType, Vec<HandlerEntry>>,
62
63 custom_handlers: HashMap<String, Vec<HandlerEntry>>,
65
66 next_handler_id: AtomicU64,
68}
69
70#[allow(deprecated)]
71impl EventRegistry {
72 pub fn new() -> Self {
74 Self {
75 handlers: HashMap::new(),
76 custom_handlers: HashMap::new(),
77 next_handler_id: AtomicU64::new(1),
78 }
79 }
80
81 pub fn register(
108 &mut self,
109 event_type: EventType,
110 priority: i32,
111 plugin_name: &str,
112 handler: EventHandler,
113 ) -> u64 {
114 let id = self.next_handler_id.fetch_add(1, Ordering::SeqCst);
115 let entry = HandlerEntry::new(id, plugin_name, priority, handler);
116
117 match event_type {
118 EventType::Custom(ref name) => {
119 let name = name.clone();
120 let handlers = self.custom_handlers.entry(name).or_insert_with(Vec::new);
121 handlers.push(entry);
122
123 handlers.sort_by(|a, b| b.priority.cmp(&a.priority));
125 }
126 _ => {
127 let handlers = self.handlers.entry(event_type).or_insert_with(Vec::new);
128 handlers.push(entry);
129
130 handlers.sort_by(|a, b| b.priority.cmp(&a.priority));
132 }
133 }
134
135 id
136 }
137
138 pub fn unregister(&mut self, handler_id: u64) -> bool {
144 for handlers in self.handlers.values_mut() {
146 if let Some(pos) = handlers.iter().position(|h| h.id == handler_id) {
147 handlers.remove(pos);
148 return true;
149 }
150 }
151
152 for handlers in self.custom_handlers.values_mut() {
154 if let Some(pos) = handlers.iter().position(|h| h.id == handler_id) {
155 handlers.remove(pos);
156 return true;
157 }
158 }
159
160 false
161 }
162
163 pub fn unregister_plugin(&mut self, plugin_name: &str) -> usize {
169 let mut count = 0;
170
171 for handlers in self.handlers.values_mut() {
173 let before = handlers.len();
174 handlers.retain(|h| h.plugin_name != plugin_name);
175 count += before - handlers.len();
176 }
177
178 for handlers in self.custom_handlers.values_mut() {
180 let before = handlers.len();
181 handlers.retain(|h| h.plugin_name != plugin_name);
182 count += before - handlers.len();
183 }
184
185 count
186 }
187
188 pub fn dispatch(&self, args: &EventArgs) -> Vec<EventResult> {
198 let handlers = match &args.event_type {
199 EventType::Custom(name) => self.custom_handlers.get(name).map(|h| h.as_slice()),
200 _ => self.handlers.get(&args.event_type).map(|h| h.as_slice()),
201 };
202
203 let Some(handlers) = handlers else {
204 return Vec::new();
205 };
206
207 let mut results = Vec::with_capacity(handlers.len());
208
209 for handler_entry in handlers {
210 let result = handler_entry.call(args);
211
212 let should_stop = result.is_stop();
214 results.push(result);
215
216 if should_stop {
217 break;
218 }
219 }
220
221 results
222 }
223
224 pub fn get_handlers(&self, event_type: &EventType) -> &[HandlerEntry] {
228 match event_type {
229 EventType::Custom(name) => self
230 .custom_handlers
231 .get(name)
232 .map(|h| h.as_slice())
233 .unwrap_or(&[]),
234 _ => self
235 .handlers
236 .get(event_type)
237 .map(|h| h.as_slice())
238 .unwrap_or(&[]),
239 }
240 }
241
242 pub fn handler_count(&self, event_type: &EventType) -> usize {
244 self.get_handlers(event_type).len()
245 }
246
247 pub fn total_handler_count(&self) -> usize {
249 let standard_count: usize = self.handlers.values().map(|v| v.len()).sum();
250 let custom_count: usize = self.custom_handlers.values().map(|v| v.len()).sum();
251 standard_count + custom_count
252 }
253
254 pub fn clear_event(&mut self, event_type: &EventType) {
256 match event_type {
257 EventType::Custom(name) => {
258 self.custom_handlers.remove(name);
259 }
260 _ => {
261 self.handlers.remove(event_type);
262 }
263 }
264 }
265
266 pub fn clear_all(&mut self) {
268 self.handlers.clear();
269 self.custom_handlers.clear();
270 }
271
272 pub fn registered_events(&self) -> Vec<EventType> {
274 let mut events: Vec<EventType> = self.handlers.keys().cloned().collect();
275
276 for custom_name in self.custom_handlers.keys() {
277 events.push(EventType::Custom(custom_name.clone()));
278 }
279
280 events
281 }
282}
283
284#[allow(deprecated)]
285impl Default for EventRegistry {
286 fn default() -> Self {
287 Self::new()
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use super::*;
294 use std::sync::{Arc, Mutex};
295
296 #[test]
297 fn test_registry_creation() {
298 let registry = EventRegistry::new();
299 assert_eq!(registry.total_handler_count(), 0);
300 }
301
302 #[test]
303 fn test_register_and_dispatch() {
304 let mut registry = EventRegistry::new();
305 let called = Arc::new(Mutex::new(false));
306 let called_clone = Arc::clone(&called);
307
308 let id = registry.register(
309 EventType::Bell,
310 100,
311 "test-plugin",
312 Box::new(move |_| {
313 *called_clone.lock().unwrap() = true;
314 EventResult::Continue
315 }),
316 );
317
318 assert_eq!(id, 1);
319 assert_eq!(registry.handler_count(&EventType::Bell), 1);
320
321 let args = EventArgs::new(EventType::Bell);
322 let results = registry.dispatch(&args);
323
324 assert_eq!(results.len(), 1);
325 assert!(results[0].is_continue());
326 assert!(*called.lock().unwrap());
327 }
328
329 #[test]
330 fn test_priority_ordering() {
331 let mut registry = EventRegistry::new();
332 let order = Arc::new(Mutex::new(Vec::new()));
333
334 for (i, priority) in [10, 50, 30].iter().enumerate() {
335 let order_clone = Arc::clone(&order);
336 registry.register(
337 EventType::Bell,
338 *priority,
339 &format!("plugin-{}", i),
340 Box::new(move |_| {
341 order_clone.lock().unwrap().push(*priority);
342 EventResult::Continue
343 }),
344 );
345 }
346
347 let args = EventArgs::new(EventType::Bell);
348 registry.dispatch(&args);
349
350 let order = order.lock().unwrap();
352 assert_eq!(*order, vec![50, 30, 10]);
353 }
354
355 #[test]
356 fn test_stop_processing() {
357 let mut registry = EventRegistry::new();
358 let call_count = Arc::new(Mutex::new(0));
359
360 for i in 0..3 {
361 let call_count_clone = Arc::clone(&call_count);
362 registry.register(
363 EventType::Bell,
364 100 - i,
365 &format!("plugin-{}", i),
366 Box::new(move |_| {
367 *call_count_clone.lock().unwrap() += 1;
368 if i == 1 {
369 EventResult::Stop
370 } else {
371 EventResult::Continue
372 }
373 }),
374 );
375 }
376
377 let args = EventArgs::new(EventType::Bell);
378 let results = registry.dispatch(&args);
379
380 assert_eq!(*call_count.lock().unwrap(), 2);
382 assert_eq!(results.len(), 2);
383 assert!(results[1].is_stop());
384 }
385
386 #[test]
387 fn test_unregister() {
388 let mut registry = EventRegistry::new();
389
390 let id = registry.register(
391 EventType::Bell,
392 100,
393 "test",
394 Box::new(|_| EventResult::Continue),
395 );
396
397 assert_eq!(registry.handler_count(&EventType::Bell), 1);
398 assert!(registry.unregister(id));
399 assert_eq!(registry.handler_count(&EventType::Bell), 0);
400 assert!(!registry.unregister(id)); }
402
403 #[test]
404 fn test_unregister_plugin() {
405 let mut registry = EventRegistry::new();
406
407 registry.register(
408 EventType::Bell,
409 100,
410 "plugin-a",
411 Box::new(|_| EventResult::Continue),
412 );
413 registry.register(
414 EventType::Bell,
415 90,
416 "plugin-b",
417 Box::new(|_| EventResult::Continue),
418 );
419 registry.register(
420 EventType::TabCreated,
421 100,
422 "plugin-a",
423 Box::new(|_| EventResult::Continue),
424 );
425
426 assert_eq!(registry.total_handler_count(), 3);
427
428 let removed = registry.unregister_plugin("plugin-a");
429 assert_eq!(removed, 2);
430 assert_eq!(registry.total_handler_count(), 1);
431 }
432
433 #[test]
434 fn test_custom_events() {
435 let mut registry = EventRegistry::new();
436 let called = Arc::new(Mutex::new(false));
437 let called_clone = Arc::clone(&called);
438
439 registry.register(
440 EventType::Custom("my-event".to_string()),
441 100,
442 "test",
443 Box::new(move |_| {
444 *called_clone.lock().unwrap() = true;
445 EventResult::Continue
446 }),
447 );
448
449 let args = EventArgs::new(EventType::Custom("my-event".to_string()));
450 registry.dispatch(&args);
451
452 assert!(*called.lock().unwrap());
453 }
454
455 #[test]
456 fn test_clear_operations() {
457 let mut registry = EventRegistry::new();
458
459 registry.register(
460 EventType::Bell,
461 100,
462 "test",
463 Box::new(|_| EventResult::Continue),
464 );
465 registry.register(
466 EventType::TabCreated,
467 100,
468 "test",
469 Box::new(|_| EventResult::Continue),
470 );
471
472 assert_eq!(registry.total_handler_count(), 2);
473
474 registry.clear_event(&EventType::Bell);
475 assert_eq!(registry.total_handler_count(), 1);
476
477 registry.clear_all();
478 assert_eq!(registry.total_handler_count(), 0);
479 }
480
481 #[test]
482 fn test_registered_events() {
483 let mut registry = EventRegistry::new();
484
485 registry.register(
486 EventType::Bell,
487 100,
488 "test",
489 Box::new(|_| EventResult::Continue),
490 );
491 registry.register(
492 EventType::Custom("test".to_string()),
493 100,
494 "test",
495 Box::new(|_| EventResult::Continue),
496 );
497
498 let events = registry.registered_events();
499 assert_eq!(events.len(), 2);
500 assert!(events.contains(&EventType::Bell));
501 assert!(events.contains(&EventType::Custom("test".to_string())));
502 }
503
504 #[test]
505 fn test_modified_result() {
506 let mut registry = EventRegistry::new();
507
508 registry.register(
509 EventType::Output,
510 100,
511 "test",
512 Box::new(|_| EventResult::Modified(vec![1, 2, 3])),
513 );
514
515 let args = EventArgs::new(EventType::Output);
516 let results = registry.dispatch(&args);
517
518 assert_eq!(results.len(), 1);
519 assert_eq!(results[0].as_modified(), Some(&[1, 2, 3][..]));
520 }
521}