Skip to content

Instantly share code, notes, and snippets.

@robert-king
Created October 6, 2025 19:58
Show Gist options
  • Save robert-king/277b765c3d27d80f4f9592d8d1b0d7da to your computer and use it in GitHub Desktop.
Save robert-king/277b765c3d27d80f4f9592d8d1b0d7da to your computer and use it in GitHub Desktop.
typesafe event registry
use std::marker::PhantomData;
use typemap::{Key, TypeMap};
struct EventListenerKey<E>(PhantomData<E>);
trait EventListner<E>: FnMut(&E) -> () + 'static {}
impl<F, E> EventListner<E> for F where F: FnMut(&E) -> () + 'static {}
impl<E: 'static> Key for EventListenerKey<E> {
type Value = Vec<Box<dyn EventListner<E>>>;
}
struct EventDispatcher(TypeMap);
impl EventDispatcher {
fn new() -> Self {
EventDispatcher(TypeMap::new())
}
fn add_listener<E: 'static>(&mut self, f: impl EventListner<E>) {
let e = self.0.entry::<EventListenerKey<E>>().or_insert(vec![]);
e.push(Box::new(f));
}
fn trigger<E: 'static>(&mut self, event: &E) {
if let Some(listeners) = self.0.get_mut::<EventListenerKey<E>>() {
for listener in listeners {
listener(event);
}
}
}
}
#[derive(Debug)]
struct Blah {
x: i32,
}
fn main() {
let mut events = EventDispatcher::new();
events.add_listener(|blah: &Blah| {
println!("blah {blah:?}");
});
events.trigger(&Blah { x: 3 });
events.add_listener(|blah: &i32| {
println!("blah {blah:?}");
});
events.trigger(&5);
events.add_listener(|blah: &i32| {
println!("woot {blah:?}");
});
events.trigger(&53);
println!("done");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment