pkecs 8.0.0

Another ECS implementation.
Documentation
//! Provides contracts and data structures which utilize components.

use std::{any::Any, collections::HashMap, hash::Hash};

/// A type-erased, contiguous span of components.
pub trait ErasedComponentChannel {
    /// Upcasts [`self`] as [`Any`].
    fn as_any(&self) -> &dyn Any;

    /// Upcasts [`self`] as [`Any`].
    fn as_any_mut(&mut self) -> &mut dyn Any;
}

/// A heterogenous collection of components.
pub struct ComponentChannel<T> {
    components: Vec<T>,
}

impl<T> ComponentChannel<T> {
    /// Retrieves an immutable iterator over [`self`].
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.components.iter()
    }

    /// Retrieves a mutable iterator over [`self`].
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.components.iter_mut()
    }

    /// Adds a component onto [`self`].
    pub fn push(&mut self, component: T) {
        self.components.push(component);
    }
}

impl<T> ComponentChannel<T> {
    /// Initializes a new, empty instance of [`self`].
    pub fn new() -> Self {
        let components = vec![];

        Self { components }
    }

    /// Initializes a new, empty instance of [`self`] within a [`Box`].
    pub fn new_box() -> Box<Self> {
        let this = Self::new();

        Box::new(this)
    }
}

impl<T> ErasedComponentChannel for ComponentChannel<T>
    where
        T: 'static,
{
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

/// An indexed map of components.
pub struct ComponentMap<TKey, TValue> {
    components: HashMap<TKey, TValue>,
}

impl<TKey, TValue> ComponentMap<TKey, TValue>
    where
        TKey: Eq + Hash,
{
    /// Initializes a new, empty [`ComponentMap`].
    pub fn new() -> Self {
        let components = HashMap::new();

        Self { components }
    }

    /// Initializes a new, empty instance of [`self`] in a [`Box`].
    pub fn new_box() -> Box<Self> {
        let this = Self::new();

        Box::new(this)
    }

    /// Inserts a component into [`self`].
    pub fn insert(&mut self, key: TKey, component: TValue) -> bool {
        self.components
            .insert(key, component)
            .is_some()
    }

    /// Returns an immutable reference to a component via their key.
    pub fn get(&self, key: &TKey) -> Option<&TValue> {
        self.components.get(key)
    }

    /// Returns a mutable reference to a component via their key.
    pub fn get_mut(&mut self, key: &TKey) -> Option<&mut TValue> {
        self.components.get_mut(key)
    }

    /// Returns an [`Iterator`] over all key-value pairs in [`self`].
    pub fn iter(&self) -> impl Iterator<Item = (&TKey, &TValue)> {
        self.components.iter()
    }

    /// Returns an [`Iterator`] over all key-value pairs in [`self`].
    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&TKey, &mut TValue)> {
        self.components.iter_mut()
    }
}

impl<TKey, TValue> ErasedComponentChannel for ComponentMap<TKey, TValue>
    where
        TKey: 'static,
        TValue: 'static,
{
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}