#![allow(unsafe_code)]
#![forbid(unused_must_use)]
use std::cell::Cell;
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, RwLock, Weak};
pub mod prelude {
pub use crate::{Event, EventHandle, EventInvocationError, Invoke};
}
pub type FnEventHandlerDelegate<TEventArgs> = fn(TEventArgs) -> ();
pub struct Event<TEventArgs = ()> {
handlers: Arc<MapLocked<TEventArgs>>,
}
unsafe impl<TEventArgs: Send + Sync> Sync for Event<TEventArgs> {}
enum HandlerType<TEventArgs> {
BoxedFn(Box<dyn Fn(TEventArgs) + Send>),
BoxedFnOnce(Cell<Option<Box<dyn FnOnce(TEventArgs) + Send>>>),
Function(FnEventHandlerDelegate<TEventArgs>),
}
unsafe impl<TEventArgs: Send + Sync> Sync for HandlerType<TEventArgs> {}
struct MapLocked<TEventArgs>(RwLock<MapInner<TEventArgs>>);
type MapInner<TEventArgs> = BTreeMap<HandleKey, HandlerType<TEventArgs>>;
#[must_use = "This handle must be held alive for as long as the event should be used."]
pub struct EventHandle<TEventArgs> {
key: HandleKey,
pointer: Weak<MapLocked<TEventArgs>>,
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
enum HandleKey {
PtrOfBox(usize),
FunctionPointer(usize),
}
impl Hash for HandleKey {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
HandleKey::PtrOfBox(ptr) => {
let address = ptr as *const usize as usize;
address.hash(state)
}
HandleKey::FunctionPointer(ptr) => {
let address = ptr as *const usize as usize;
address.hash(state)
}
}
}
}
impl<TEventArgs> EventHandle<TEventArgs> {
fn new(key: HandleKey, pointer: &Arc<MapLocked<TEventArgs>>) -> Self {
Self {
key,
pointer: Arc::downgrade(pointer),
}
}
pub fn is_valid(&self) -> bool {
self.pointer.strong_count() > 0
}
pub fn invoke(&self, args: TEventArgs) -> Result<(), EventInvocationError>
where
TEventArgs: Clone,
{
if let Some(ptr) = self.pointer.upgrade() {
ptr.invoke(args);
Ok(())
} else {
Err(EventInvocationError::EventDropped)
}
}
}
#[derive(Debug, PartialEq)]
pub enum EventInvocationError {
EventDropped,
}
impl Display for EventInvocationError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EventInvocationError::EventDropped => write!(
f,
"Event could not be invoked because it was already dropped"
),
}
}
}
impl Error for EventInvocationError {}
impl<TEventArgs> Drop for EventHandle<TEventArgs> {
fn drop(&mut self) {
if let Some(lock) = self.pointer.upgrade() {
let mut handlers = lock.write().unwrap();
handlers.remove(&self.key);
}
}
}
impl<TEventArgs> Event<TEventArgs> {
pub fn new() -> Self
where
TEventArgs: Clone,
{
Self {
handlers: Arc::new(MapLocked::new(MapInner::new())),
}
}
pub fn add_fn<T>(&self, handler: T) -> Result<EventHandle<TEventArgs>, String>
where
T: Fn(TEventArgs) -> () + Send + 'static,
{
let handler = Box::new(handler);
let key = HandleKey::PtrOfBox((&*handler as *const _) as usize);
let mut handlers = self.handlers.write().unwrap();
let entry = HandlerType::BoxedFn(handler);
match handlers.insert(key, entry) {
None => Ok(EventHandle::new(key, &self.handlers)),
Some(_) => Err(String::from("The handler was already registered")),
}
}
pub fn add_fnonce<T>(&self, handler: T) -> Result<EventHandle<TEventArgs>, String>
where
T: FnOnce(TEventArgs) -> () + Send + 'static,
{
let handler = Box::new(handler);
let key = HandleKey::PtrOfBox((&*handler as *const _) as usize);
let mut handlers = self.handlers.write().unwrap();
let entry = HandlerType::BoxedFnOnce(Cell::new(Some(handler)));
match handlers.insert(key, entry) {
None => Ok(EventHandle::new(key, &self.handlers)),
Some(_) => Err(String::from("The handler was already registered")),
}
}
pub fn add_ptr(
&self,
handler: FnEventHandlerDelegate<TEventArgs>,
) -> Result<EventHandle<TEventArgs>, String> {
let key = HandleKey::FunctionPointer((&handler as *const _) as usize);
let mut handlers = self.handlers.write().unwrap();
let entry = HandlerType::Function(handler);
match handlers.insert(key, entry) {
None => Ok(EventHandle::new(key, &self.handlers)),
Some(_) => Err(String::from("The handler was already registered")),
}
}
pub fn len(&self) -> usize {
self.handlers.read().unwrap().len()
}
pub fn invoke(&self, args: TEventArgs)
where
TEventArgs: Clone,
{
self.handlers.invoke(args)
}
}
impl Default for Event {
fn default() -> Self {
Self::new()
}
}
impl<TEventArgs> MapLocked<TEventArgs>
where
TEventArgs: Clone,
{
const fn new(inner: MapInner<TEventArgs>) -> Self {
Self(RwLock::new(inner))
}
fn invoke(&self, args: TEventArgs) {
let mut unregister_list = Vec::new();
{
let handlers = self.read().unwrap();
for (key, entry) in handlers.iter() {
let args = args.clone();
match &entry {
HandlerType::Function(fun) => fun(args),
HandlerType::BoxedFn(fun) => fun(args),
HandlerType::BoxedFnOnce(cell) => {
let fun = cell.replace(None);
if fun.is_some() {
(fun.unwrap())(args);
}
unregister_list.push(key.clone());
}
}
}
}
if !unregister_list.is_empty() {
let mut handlers = self.write().unwrap();
for key in unregister_list {
handlers.remove(&key);
}
}
}
}
impl<TEventArgs> Deref for MapLocked<TEventArgs> {
type Target = RwLock<MapInner<TEventArgs>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<TEventArgs> DerefMut for MapLocked<TEventArgs> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub trait Invoke<TEventArgs>
where
TEventArgs: Clone,
{
fn invoke(&self, args: TEventArgs);
}
impl<TEventArgs> Invoke<TEventArgs> for Event<TEventArgs>
where
TEventArgs: Clone,
{
fn invoke(&self, args: TEventArgs) {
self.invoke(args)
}
}
impl<TEventArgs> Invoke<TEventArgs> for EventHandle<TEventArgs>
where
TEventArgs: Clone,
{
fn invoke(&self, args: TEventArgs) {
self.invoke(args).ok();
}
}
#[cfg(test)]
mod tests {
use super::*;
fn dummy(_args: ()) {
println!("Dummy called.");
}
#[test]
fn new_handler_has_no_registrations() {
let handler = Event::<()>::new();
assert_eq!(handler.len(), 0);
}
#[test]
#[allow(unused_variables)]
fn can_add_fn() {
let handler = Event::<()>::new();
let handle = handler.add_fn(dummy).unwrap();
assert_eq!(handler.len(), 1);
handler.invoke(());
}
#[test]
#[allow(unused_variables)]
fn can_add_fnonce() {
let handler = Event::new();
let handle = handler.add_fnonce(dummy).unwrap();
assert_eq!(handler.len(), 1);
handler.invoke(());
assert_eq!(handler.len(), 0);
}
#[test]
#[allow(unused_variables)]
fn can_add_function_pointer() {
let handler = Event::<()>::new();
let handle = handler.add_ptr(dummy).unwrap();
assert_eq!(handler.len(), 1);
handler.invoke(());
}
#[test]
#[allow(unused_variables)]
fn cannot_register_same_function_twice() {
let handler = Event::new();
let handle = handler.add_ptr(dummy).unwrap();
assert!(handler.add_ptr(dummy).is_err());
}
#[test]
fn can_remove_handlers() {
let handler = Event::new();
let handle = handler.add_fn(dummy).unwrap();
assert_eq!(handler.len(), 1);
drop(handle);
assert_eq!(handler.len(), 0);
}
#[test]
fn handler_is_sync() {
let handler: Event = Event::new();
let _sync: Box<dyn Sync> = Box::new(handler);
}
}