use std::panic::RefUnwindSafe;
use crate::{DynEvent, Event};
pub trait Handle {
type EventType: Event;
fn handle(&self, event: Self::EventType) -> ();
}
pub struct Handler<T: Event> {
handle: Box<dyn Fn(T) + Send + Sync>,
}
impl<T: Event> RefUnwindSafe for Handler<T> {}
impl<T: Event> Handler<T> {
pub fn new<F>(f: F) -> Self
where
F: Fn(T) + Send + Sync + 'static,
{
Handler {
handle: Box::new(f),
}
}
}
pub trait DynHandle: Send + Sync + RefUnwindSafe {
fn dyn_handle(&self, event: &dyn DynEvent) -> ();
}
impl<T: Event> DynHandle for Handler<T> {
fn dyn_handle(&self, event: &dyn DynEvent) {
if let Some(event_data) = event.get_data().downcast_ref::<T>() {
(self.handle)(event_data.clone())
}
}
}
impl<T, U> DynHandle for U
where
T: Event,
U: Handle<EventType = T> + Send + Sync + RefUnwindSafe,
{
fn dyn_handle(&self, event: &dyn DynEvent) {
if let Some(event_data) = event.get_data().downcast_ref::<T>() {
self.handle(event_data.clone())
}
}
}
pub trait HandleMut {
type EventType: Event;
fn handle_mut(&mut self, event: Self::EventType) -> ();
}
pub trait DynHandleMut {
fn dyn_handle_mut(&mut self, event: &dyn DynEvent) -> ();
}
impl<T, U> DynHandleMut for U
where
T: Event,
U: HandleMut<EventType = T> + Send + Sync + RefUnwindSafe,
{
fn dyn_handle_mut(&mut self, event: &dyn DynEvent) {
if let Some(event_data) = event.get_data().downcast_ref::<T>() {
self.handle_mut(event_data.clone())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug, PartialEq)]
struct MyEvent(pub i32);
impl Event for MyEvent {}
#[derive(Clone, Debug)]
struct OtherEvent;
impl Event for OtherEvent {}
struct TestHandle {
called: Arc<Mutex<bool>>,
}
impl Handle for TestHandle {
type EventType = MyEvent;
fn handle(&self, event: MyEvent) {
assert_eq!(event.0, 99);
*self.called.lock().unwrap() = true;
}
}
#[derive(Clone, Debug, PartialEq)]
struct MutEvent(pub i32);
impl Event for MutEvent {}
struct TestHandleMut {
called: Arc<Mutex<bool>>,
last_value: Arc<Mutex<Option<i32>>>,
}
impl HandleMut for TestHandleMut {
type EventType = MutEvent;
fn handle_mut(&mut self, event: MutEvent) {
*self.called.lock().unwrap() = true;
*self.last_value.lock().unwrap() = Some(event.0);
}
}
#[test]
fn test_dyn_handle_calls_handle_on_matching_type() {
let called = Arc::new(Mutex::new(false));
let called_clone = called.clone();
let handler = Handler::new(move |event: MyEvent| {
assert_eq!(event.0, 42);
*called_clone.lock().unwrap() = true;
});
let event = MyEvent(42);
handler.dyn_handle(&event);
assert!(*called.lock().unwrap());
}
#[test]
fn test_dyn_handle_does_not_call_handle_on_non_matching_type() {
let called = Arc::new(Mutex::new(false));
let called_clone = called.clone();
let handler = Handler::new(move |_event: MyEvent| {
*called_clone.lock().unwrap() = true;
});
let other_event = OtherEvent;
handler.dyn_handle(&other_event);
assert!(!*called.lock().unwrap());
}
#[test]
fn test_dyn_handle_for_handle_impl_matching_type() {
let called = Arc::new(Mutex::new(false));
let handler = TestHandle {
called: called.clone(),
};
let event = MyEvent(99);
DynHandle::dyn_handle(&handler, &event);
assert!(*called.lock().unwrap());
}
#[test]
fn test_dyn_handle_for_handle_impl_non_matching_type() {
let called = Arc::new(Mutex::new(false));
let handler = TestHandle {
called: called.clone(),
};
let other_event = OtherEvent;
DynHandle::dyn_handle(&handler, &other_event);
assert!(!*called.lock().unwrap());
}
#[test]
fn test_dyn_handle_mut_calls_handle_mut_on_matching_type() {
let called = Arc::new(Mutex::new(false));
let last_value = Arc::new(Mutex::new(None));
let mut handler = TestHandleMut {
called: called.clone(),
last_value: last_value.clone(),
};
let event = MutEvent(123);
DynHandleMut::dyn_handle_mut(&mut handler, &event);
assert!(*called.lock().unwrap());
assert_eq!(*last_value.lock().unwrap(), Some(123));
}
#[test]
fn test_dyn_handle_mut_does_not_call_handle_mut_on_non_matching_type() {
let called = Arc::new(Mutex::new(false));
let last_value = Arc::new(Mutex::new(None));
let mut handler = TestHandleMut {
called: called.clone(),
last_value: last_value.clone(),
};
let other_event = OtherEvent;
DynHandleMut::dyn_handle_mut(&mut handler, &other_event);
assert!(!*called.lock().unwrap());
assert_eq!(*last_value.lock().unwrap(), None);
}
}