use std::hash::Hash;
pub mod dispatcher;
pub use dispatcher::Dispatcher;
pub trait Listener<T>
where
T: PartialEq + Eq + Hash + Clone + 'static,
{
fn on_event(&self, event: &T) -> Option<DispatcherRequest>;
}
#[derive(Debug)]
pub(crate) enum ExecuteRequestsResult {
Finished,
Stopped,
}
#[derive(Debug)]
pub enum DispatcherRequest {
StopListening,
StopPropagation,
StopListeningAndPropagation,
}
pub(crate) fn execute_dispatcher_requests<T, F>(
vec: &mut Vec<T>,
mut function: F,
) -> ExecuteRequestsResult
where
F: FnMut(&T) -> Option<DispatcherRequest>,
{
let mut index = 0;
loop {
if index < vec.len() {
match function(&vec[index]) {
None => index += 1,
Some(DispatcherRequest::StopListening) => {
vec.swap_remove(index);
}
Some(DispatcherRequest::StopPropagation) => return ExecuteRequestsResult::Stopped,
Some(DispatcherRequest::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<DispatcherRequest> {
match *x {
0 => Some(DispatcherRequest::StopListening),
1 => Some(DispatcherRequest::StopPropagation),
2 => Some(DispatcherRequest::StopListeningAndPropagation),
_ => None,
}
}
#[test]
fn stop_listening() {
let mut vec = vec![0, 0, 0, 1, 1, 1, 1];
execute_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_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_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_dispatcher_requests(&mut vec, map_usize_to_request);
assert_eq!(vec, [0]);
}
}
}