atomr_patterns/
extensions.rs1use std::sync::Arc;
14
15use crate::PatternError;
16
17pub type CommandInterceptor<C, E> = Arc<dyn Fn(&C) -> Result<(), PatternError<E>> + Send + Sync + 'static>;
20
21pub type EventListener<EV> = Arc<dyn Fn(&EV) + Send + Sync + 'static>;
24
25pub struct ExtensionSlots<C, EV, DE> {
28 pub command_interceptors: Vec<CommandInterceptor<C, DE>>,
29 pub event_listeners: Vec<EventListener<EV>>,
30 pub command_taps: Vec<tokio::sync::mpsc::UnboundedSender<C>>,
31 pub event_taps: Vec<tokio::sync::mpsc::UnboundedSender<EV>>,
32}
33
34impl<C, EV, DE> Default for ExtensionSlots<C, EV, DE> {
35 fn default() -> Self {
36 Self {
37 command_interceptors: Vec::new(),
38 event_listeners: Vec::new(),
39 command_taps: Vec::new(),
40 event_taps: Vec::new(),
41 }
42 }
43}
44
45impl<C, EV, DE> Clone for ExtensionSlots<C, EV, DE> {
46 fn clone(&self) -> Self {
47 Self {
48 command_interceptors: self.command_interceptors.clone(),
49 event_listeners: self.event_listeners.clone(),
50 command_taps: self.command_taps.clone(),
51 event_taps: self.event_taps.clone(),
52 }
53 }
54}
55
56impl<C, EV, DE> ExtensionSlots<C, EV, DE> {
57 pub fn run_interceptors(&self, cmd: &C) -> Result<(), PatternError<DE>> {
59 for hook in &self.command_interceptors {
60 hook(cmd)?;
61 }
62 Ok(())
63 }
64
65 pub fn notify_listeners(&self, ev: &EV) {
67 for hook in &self.event_listeners {
68 hook(ev);
69 }
70 }
71}
72
73impl<C: Clone, EV, DE> ExtensionSlots<C, EV, DE> {
74 pub fn push_command_taps(&mut self, cmd: &C) {
77 self.command_taps.retain(|tx| tx.send(cmd.clone()).is_ok());
78 }
79}
80
81impl<C, EV: Clone, DE> ExtensionSlots<C, EV, DE> {
82 pub fn push_event_taps(&mut self, ev: &EV) {
85 self.event_taps.retain(|tx| tx.send(ev.clone()).is_ok());
86 }
87}