#[cfg(feature = "parallel")]
use rayon::ThreadPool;
use std::hash::Hash;
#[cfg(feature = "async")]
pub mod async_dispatcher;
#[cfg(feature = "parallel")]
pub mod parallel_dispatcher;
#[cfg(feature = "parallel")]
pub mod priority_dispatcher;
#[cfg(feature = "async")]
pub use async_dispatcher::AsyncDispatcher;
#[cfg(feature = "parallel")]
pub use parallel_dispatcher::ParallelDispatcher;
#[cfg(feature = "parallel")]
pub use priority_dispatcher::PriorityDispatcher;
#[cfg(feature = "parallel")]
#[derive(Debug)]
#[allow(clippy::pub_enum_variant_names)]
pub enum PriorityDispatcherResult {
StopListening,
StopPropagation,
StopListeningAndPropagation,
}
#[derive(Debug)]
#[cfg(feature = "parallel")]
pub(crate) enum ExecuteRequestsResult {
Finished,
Stopped,
}
#[cfg(feature = "parallel")]
pub trait Listener<T>
where
T: PartialEq + Eq + Hash + Clone + 'static,
{
fn on_event(&self, event: &T) -> Option<ParallelDispatchResult>;
}
#[cfg(feature = "parallel")]
pub(crate) fn execute_sync_dispatcher_requests<T, F>(
vec: &mut Vec<T>,
mut function: F,
) -> ExecuteRequestsResult
where
F: FnMut(&T) -> Option<PriorityDispatcherResult>,
{
let mut index = 0;
loop {
if index < vec.len() {
match function(&vec[index]) {
None => index += 1,
Some(PriorityDispatcherResult::StopListening) => {
vec.swap_remove(index);
}
Some(PriorityDispatcherResult::StopPropagation) => {
return ExecuteRequestsResult::Stopped
}
Some(PriorityDispatcherResult::StopListeningAndPropagation) => {
vec.swap_remove(index);
return ExecuteRequestsResult::Stopped;
}
}
} else {
return ExecuteRequestsResult::Finished;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
mod execute_sync_dispatcher_requests {
use super::*;
#[allow(clippy::trivially_copy_pass_by_ref)]
const fn map_usize_to_request(x: &usize) -> Option<PriorityDispatcherResult> {
match *x {
0 => Some(PriorityDispatcherResult::StopListening),
1 => Some(PriorityDispatcherResult::StopPropagation),
2 => Some(PriorityDispatcherResult::StopListeningAndPropagation),
_ => None,
}
}
#[test]
fn stop_listening() {
let mut vec = vec![0, 0, 0, 1, 1, 1, 1];
execute_sync_dispatcher_requests(&mut vec, map_usize_to_request);
assert_eq!(vec, [1, 0, 0, 1, 1, 1]);
}
#[test]
fn empty_vec() {
let mut vec = Vec::new();
execute_sync_dispatcher_requests(&mut vec, map_usize_to_request);
assert!(vec.is_empty());
}
#[test]
fn removing_all() {
let mut vec = vec![0, 0, 0, 0, 0, 0, 0];
execute_sync_dispatcher_requests(&mut vec, map_usize_to_request);
assert!(vec.is_empty());
}
#[test]
fn remove_one_element_and_stop() {
let mut vec = vec![2, 0];
execute_sync_dispatcher_requests(&mut vec, map_usize_to_request);
assert_eq!(vec, [0]);
}
}
}
#[cfg(feature = "parallel")]
#[derive(Debug)]
pub enum ParallelDispatchResult {
StopListening,
}
#[derive(Debug)]
#[cfg(feature = "async")]
pub enum AsyncDispatchResult {
StopListening,
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
pub trait AsyncListener<T>
where
T: PartialEq + Eq + Hash + Clone + Send + Sync + 'static,
{
async fn on_event(&self, event: &T) -> Option<AsyncDispatchResult>;
}
#[cfg(feature = "parallel")]
pub trait ParallelListener<T>
where
T: PartialEq + Eq + Hash + Clone + Send + Sync + 'static,
{
fn on_event(&self, event: &T) -> Option<ParallelDispatchResult>;
}
#[cfg(feature = "parallel")]
pub trait PriorityListener<T>
where
T: PartialEq + Eq + Hash + Clone + Send + Sync + 'static,
{
fn on_event(&self, event: &T) -> Option<PriorityDispatcherResult>;
}