use std::sync::Arc;
use crate::PatternError;
pub type CommandInterceptor<C, E> = Arc<dyn Fn(&C) -> Result<(), PatternError<E>> + Send + Sync + 'static>;
pub type EventListener<EV> = Arc<dyn Fn(&EV) + Send + Sync + 'static>;
pub struct ExtensionSlots<C, EV, DE> {
pub command_interceptors: Vec<CommandInterceptor<C, DE>>,
pub event_listeners: Vec<EventListener<EV>>,
pub command_taps: Vec<tokio::sync::mpsc::UnboundedSender<C>>,
pub event_taps: Vec<tokio::sync::mpsc::UnboundedSender<EV>>,
}
impl<C, EV, DE> Default for ExtensionSlots<C, EV, DE> {
fn default() -> Self {
Self {
command_interceptors: Vec::new(),
event_listeners: Vec::new(),
command_taps: Vec::new(),
event_taps: Vec::new(),
}
}
}
impl<C, EV, DE> Clone for ExtensionSlots<C, EV, DE> {
fn clone(&self) -> Self {
Self {
command_interceptors: self.command_interceptors.clone(),
event_listeners: self.event_listeners.clone(),
command_taps: self.command_taps.clone(),
event_taps: self.event_taps.clone(),
}
}
}
impl<C, EV, DE> ExtensionSlots<C, EV, DE> {
pub fn run_interceptors(&self, cmd: &C) -> Result<(), PatternError<DE>> {
for hook in &self.command_interceptors {
hook(cmd)?;
}
Ok(())
}
pub fn notify_listeners(&self, ev: &EV) {
for hook in &self.event_listeners {
hook(ev);
}
}
}
impl<C: Clone, EV, DE> ExtensionSlots<C, EV, DE> {
pub fn push_command_taps(&mut self, cmd: &C) {
self.command_taps.retain(|tx| tx.send(cmd.clone()).is_ok());
}
}
impl<C, EV: Clone, DE> ExtensionSlots<C, EV, DE> {
pub fn push_event_taps(&mut self, ev: &EV) {
self.event_taps.retain(|tx| tx.send(ev.clone()).is_ok());
}
}