deepslate 0.1.0

A high-performance Minecraft server proxy written in Rust.
Documentation
//! Type-erased event handler storage and dispatch.
//!
//! Provides the internal plumbing that makes the type-safe public API work:
//! handlers are stored as trait objects keyed by `TypeId`, and downcast back
//! to the concrete event type when dispatched.

use std::any::Any;
use std::cmp::Reverse;

use super::priority::PostOrder;

/// A type-erased event handler that can be stored in a heterogeneous collection.
///
/// This is an internal trait — users interact with the type-safe
/// `EventManager::subscribe` API instead.
pub(crate) trait ErasedHandler: Send + Sync {
    /// Call the handler with a type-erased event reference.
    ///
    /// The implementation downcasts to the concrete event type. Panics if
    /// the wrong type is passed (should never happen — the `EventManager`
    /// guarantees correct dispatch by `TypeId`).
    fn call(&self, event: &mut dyn Any);
}

/// Wrapper that implements `ErasedHandler` for a concrete `Fn(&mut E)` closure.
pub(crate) struct TypedHandler<E: 'static> {
    handler: Box<dyn Fn(&mut E) + Send + Sync>,
}

impl<E: 'static> TypedHandler<E> {
    pub(crate) fn new(handler: impl Fn(&mut E) + Send + Sync + 'static) -> Self {
        Self {
            handler: Box::new(handler),
        }
    }
}

impl<E: 'static> ErasedHandler for TypedHandler<E> {
    fn call(&self, event: &mut dyn Any) {
        let event = event
            .downcast_mut::<E>()
            .expect("EventManager dispatched wrong event type to handler");
        (self.handler)(event);
    }
}

/// A registered handler with its priority and metadata.
pub(crate) struct HandlerRegistration {
    /// Execution priority (higher values execute first).
    pub(crate) priority: PostOrder,
    /// The type-erased handler.
    pub(crate) handler: Box<dyn ErasedHandler>,
}

/// Sort handler registrations by priority (highest first).
///
/// Uses `Reverse` so that higher priority values sort earlier. Handlers at
/// the same priority level retain their registration order (stable sort).
pub(crate) fn sort_handlers(handlers: &mut [HandlerRegistration]) {
    handlers.sort_by_key(|h| Reverse(h.priority));
}