#events #event-system #bus #publish #pub-sub #subscribe #event-bus

pubsub-bus

Thread-safe one-to-many publish-subscribe event system. Simple and easy to use. It just works (hopefully).

6 stable releases

new 3.1.0 Feb 20, 2025
3.0.0 Feb 18, 2025
2.0.0 Feb 4, 2025
1.1.1 Feb 2, 2025
1.1.0 Jan 29, 2025

#174 in Concurrency

Download history 146/week @ 2025-01-25 191/week @ 2025-02-01 18/week @ 2025-02-08

355 downloads per month

MIT license

23KB
375 lines

pubsub-bus

GitHub Release

Thread-safe one-to-many event system. Simple and easy to use. It just works (hopefully).

Features:

  • 📃 Event Topic Filtering
  • 🔢 Unique event and publisher IDs
  • 🔀 Thread-safe
  • 🧱 No unsafe code

Table of Contents

⚙️ What it does (Without words)

Publishing

🚀 Quick Start

1. Add the dependency to your Cargo.toml

pubsub-bus = "3.0.0"

2. Create your events and a bus

enum Commands {
    Atack { player_id: u32 },
    Move { player_id: u32, dx: f32, dy: f32 },
}

#[derive(PartialEq)]
enum TopicIds {
    Player1,
    Player2,
}


let bus: EventBus<Commands, TopicIds> = EventBus::new();

3. Implement the Subscriber trait for your struct and subscribe it to the bus

impl Subscriber<Commands, TopicIds> for Player {
    fn on_event(&mut self, event: &BusEvent<Commands, TopicIds>) {
        let event_id = event.get_id();
        let event_source_id = event.get_source_id();
        match event.get_content() {
         ...
        }
    }
}

...

let player1 = Player { id: 1 };
bus.add_subscriber(player1);

4. Create a Publisher and pass the bus to it

pub struct Input {
    emitter: EventEmitter<Commands, TopicIds>,
}

impl Publisher<Commands, TopicIds> for Input {
    fn get_mut_emitter(&mut self) -> &mut EventEmitter<Commands, TopicIds> {
        &mut self.emitter
    }
}

...

let mut  input = Input::new();
bus.add_publisher(&mut input, None); // None -> Auto assign ID

5. Send events

input.publish(  Commands::Move { dx: 1.0, dy: 2.0 }, 
                Some(TopicIds::Player1) );
                
input.publish(  Commands::Atack, 
                Some(TopicIds::Player2) );

📖 Examples

The following example demonstrates how to exchange events between players and an input system.

fn main() {
    // Create a bus
    let bus: EventBus<Commands, TopicIds> = EventBus::new();

    // Create players, input, and attach to the bus
    let player1 = Player { id: 1 };
    let player2 = Player { id: 2 };
    let mut input = Input::new();

    bus.add_subscriber(player1);
    bus.add_subscriber(player2);
    bus.add_publisher(&mut input, Some(85)).unwrap();

    // Send some events
    input.publish(Commands::Move { dx: 1.0, dy: 2.0 }, 
                  Some(TopicIds::Player2));
    input.publish(Commands::Move { dx: 1.0, dy: 2.0 }, 
                  Some(TopicIds::Player1));
    input.publish(Commands::Atack, Some(TopicIds::Player2));
    input.publish(Commands::Atack, Some(TopicIds::Player1));
}

For the full example, see the examples/basic_game_events directory.

No runtime deps