Skip to content

Multiple events of different payloads #1

@wimvelzeboer

Description

@wimvelzeboer

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...

Metadata

Metadata

Assignees

Labels

questionFurther information is requested

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions