pkecs 9.0.0

Another ECS implementation.
Documentation
//! Contains an eventing system.

mod channel;
pub mod handler;
mod queue;

use std::{any::TypeId, collections::HashMap};
use super::world::UnsafeWorldCell;
use channel::{EventChannel, ErasedEventChannel};
use handler::into::IntoEventHandler;
use queue::{EventQueue, ErasedEventQueue};

/// A publisher-subscriber eventing system.
#[derive(Default)]
pub struct Events {
    /// Event handlers.
    ///
    /// These are keyed by the [`TypeId`] of the events they're subscribed to.
    handlers: HashMap<TypeId, Box<dyn ErasedEventChannel>>,
}

impl Events {
    /// Registers a system which responds to a specific event.
    pub fn register<E, H, P>(&mut self, handler: H)
        where
            E: 'static,
            H: IntoEventHandler<E, P> + 'static,
            P: 'static,
    {
        let id = TypeId::of::<E>();

        self.handlers
            .entry(id)
            .or_insert(EventChannel::<E>::new_box())
            .as_any_mut()
            .downcast_mut::<EventChannel<E>>()
            .map(|c| c.register(handler.into_handler()));
    }

    /// Consumes all queued events in the current execution context.
    pub fn consume(&self, cell: &UnsafeWorldCell) {
        let world = cell.get_mut();
        let queues = world.events_mut();

        queues
            .iter_mut()
            .for_each(|(id, queue)| {
                self.handlers
                    .get(id)
                    .map(|h| h.trigger_all(queue.as_mut(), cell));
            });
    }
}

/// A set of in-memory event queues.
///
/// Queues are drained during each execution context.
/// An execution context defines a single loop in an application's lifecycle.
#[derive(Default)]
pub struct EventQueues {
    /// Event queues for the current execution context.
    ///
    /// These are keyed by the [`TypeId`] of the events they contain.
    queues: HashMap<TypeId, Box<dyn ErasedEventQueue>>,
}

impl EventQueues {
    /// Queues an event for the current execution context.
    pub fn queue<E>(&mut self, event: E)
        where
            E: 'static,
    {
        let id = TypeId::of::<E>();

        self.queues
            .entry(id)
            .or_insert(EventQueue::<E>::new_box())
            .as_any_mut()
            .downcast_mut::<EventQueue<E>>()
            .map(|q| q.queue(event));
    }

    /// Mutably iterates over all queued events.
    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&TypeId, &mut Box<dyn ErasedEventQueue>)> {
        self.queues.iter_mut()
    }
}