dimitri-br / simple-event-bus Goto Github PK
View Code? Open in Web Editor NEWSimple Event Bus in Rust
License: MIT License
Simple Event Bus in Rust
License: MIT License
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...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.