Hi @dimitri-br
I like the simplicity of this event bus, I tried to add a feature to but got stranded. That probably because I am quite new to Rust.
My idea was to add the ability to have different events with any type of payload, so that you could do something like this:
fn main() {
let mut event_bus = EventBus::new();
// Add each subscriber to the event bus, two for the "foo" and one for the "bar" event
event_bus.subscribe_listener("foo".to_string(), FooOneSubscriber::new("Foo Subscriber 1".to_string()));
event_bus.subscribe_listener("foo".to_string(), FooTwoSubscriber::new("Foo Subscriber 2".to_string()));
event_bus.subscribe_listener("bar".to_string(), BarSubscriber::new("Foo Subscriber 1".to_string()));
// publish two events, one for each.
event_bus.publish("foo".to_string(), Event::new("hello".to_string())); // takes a String as payload/message
event_bus.publish("bar".to_string(), Event::new(42)); // takes a Number/u32 as payload/message
// Run through each event
event_bus.run();
}
The event name (foo
/bar
) is always a String but it should be able to take any kind of payload/message, e.g. String, u32, Struct/Trait
I started with changing the event
of EventBus
into a HashMap, but got into a conflict where I could only payloads of either a String or u32, not both. And got lost while trying to refactor everything into a Trait.
Any pointers that you can give me are very welcome!
This is the changed event_bus:
#![allow(dead_code)]
use std::collections::HashMap;
use super::Event;
use super::Subscriber;
pub struct EventBus<T> {
/// A vec of events that have been published to the event bus.
events: HashMap<String, Vec<Box<Event<T>>>>,
/// A vec of all subscribers that are linked to the event bus.
subscribers: HashMap<String, Vec<Box<dyn Subscriber<Input = T>>>>,
}
impl<T> EventBus<T> {
pub fn new() -> EventBus<T> {
EventBus {
events: HashMap::new(),
subscribers: HashMap::new(),
}
}
pub fn publish(&mut self, event_name: String, message: Event<T>) {
if self.events.contains_key(&event_name) {
self.events.get_mut(&event_name).unwrap()
.push(Box::new(message));
} else {
self.events.insert(event_name, vec![Box::new(message)]);
}
}
pub fn subscribe_listener<R: Subscriber<Input = T> + 'static>(&mut self, event_name:String, listener: R) {
if self.subscribers.contains_key(&event_name) {
self.subscribers.get_mut(&event_name).unwrap()
.push(Box::new(listener));
} else {
self.subscribers.insert(event_name, vec![Box::new(listener)]);
}
}
pub fn run(&mut self) {
for (event, messages) in self.events.drain() {
if self.subscribers.contains_key(&event) {
for listener in self.subscribers.get_mut(&event).unwrap().iter_mut() {
for message in &messages {
listener.on_event(message);
}
}
} else {
println!("No event subscribers for '{}'", event);
}
}
}
...
}
// Default
impl<T> Default for EventBus<T> {
...
}
And this is the Example to test it
use simple_event_bus::{Event, EventBus, Subscriber};
struct ExampleSubscriber {
pub name: String,
}
impl ExampleSubscriber {
pub fn new(name: String) -> ExampleSubscriber {
ExampleSubscriber { name }
}
}
impl Subscriber for ExampleSubscriber {
type Input = String;
fn on_event(&mut self, event: &Event<Self::Input>) {
println!("{} received message: {}", self.name, event.get_data());
}
}
struct NumberSubscriber {
pub name: String,
}
impl NumberSubscriber {
pub fn new(name: String) -> NumberSubscriber {
NumberSubscriber { name }
}
}
impl Subscriber for NumberSubscriber {
type Input = u32;
fn on_event(&mut self, event: &Event<Self::Input>) {
println!("{} received message: {}", self.name, event.get_data());
}
}
fn main() {
let mut event_bus = EventBus::new();
// We have to manually create and add each subscriber to the event bus.
// event_bus.subscribe_listener("bar".to_string(), ExampleSubscriber::new("Subscriber 1".to_string()));
// event_bus.subscribe_listener("bar".to_string(), ExampleSubscriber::new("Subscriber 2".to_string()));
event_bus.subscribe_listener("foo".to_string(), NumberSubscriber::new("Number Subscriber".to_string()));
// We can manually define an event and publish it to the event bus.
// event_bus.publish(Event::new("hello".to_string()));
let number: u32 = 32;
event_bus.publish("foo".to_string(), Event::new(number));
// event_bus.publish("bar".to_string(), Event::new("hello".to_string()));
// Runs through each event, and calls each listener's on_event method.
event_bus.run();
}
It works, but I can't use both ExampleSubscriber and NumberSubscriber at the same time...