pkecs 9.0.0

Another ECS implementation.
Documentation
//! Contains types for querying a component store.

use std::hash::Hash;
use super::{
    component::channel::{ComponentChannel, ComponentMap},
    system::param::SystemParameter,
    world::UnsafeWorldCell,
};

/// An immutable reference to a set of components.
pub struct Query<'c, T> {
    channel: Option<&'c ComponentChannel<T>>
}

impl<'c, T> Query<'c, T> {
    /// Initializes [`self`] from an ummutable reference to [`ComponentPool`].
    pub const fn from_channel(channel: Option<&'c ComponentChannel<T>>) -> Self {
        Self { channel }
    }

    /// Iterates over a set of components.
    ///
    /// Will return an empty [`Iterator`] if [`self`] is invalid.
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.channel
            .iter()
            .flat_map(|c| c.iter())
    }

    /// Retrieves the first component in the set.
    ///
    /// Will return [`None`] if [`self`] is invalid.
    pub fn first(&self) -> Option<&T> {
        self.iter()
            .next()
    }
}

impl<'c, T> SystemParameter for Query<'c, T>
    where
        T: 'static,
{
    fn fetch(cell: &UnsafeWorldCell) -> Self {
        let world = cell.get();
        let components = world.components();

        components.query::<T>()
    }
}

/// A mutable reference to a set of components.
pub struct QueryMut<'c, T> {
    channel: Option<&'c mut ComponentChannel<T>>,
}

impl<'c, T> QueryMut<'c, T> {
    /// Initializes [`self`] from a mutable reference to [`ComponentChannel`].
    pub const fn from_channel(channel: Option<&'c mut ComponentChannel<T>>) -> Self {
        Self { channel }
    }

    /// Iterates over a set of components.
    ///
    /// Will return an empty [`Iterator`] if [`self`] is invalid.
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        self.channel
            .iter_mut()
            .flat_map(|c| c.iter_mut())
    }

    /// Retrieves the first component in [`self`].
    ///
    /// Will return [`None`] if there are no components in the set or if it didn't exist.
    pub fn first_mut(&mut self) -> Option<&mut T> {
        self.iter_mut()
            .next()
    }
}

impl<'c, T> SystemParameter for QueryMut<'c, T>
    where
        T: 'static,
{
    fn fetch(cell: &UnsafeWorldCell) -> Self {
        let world = cell.get_mut();
        let components = world.components_mut();

        components.query_mut::<T>()
    }
}

/// An immutable query against an indexed component set.
pub struct QueryIndexed<'c, K, V> {
    channel: Option<&'c ComponentMap<K, V>>,
}

impl<'c, K, V> QueryIndexed<'c, K, V>
    where
        K: Eq + Hash,
{
    /// Initializes [`self`] from an immutable reference to [`ComponentMap`].
    pub const fn from_channel(channel: Option<&'c ComponentMap<K, V>>) -> Self {
        Self { channel }
    }

    /// Gets an immutable reference to a component via it's key.
    pub fn get(&self, key: &K) -> Option<&'c V> {
        self.channel.and_then(|c| c.get(key))
    }

    /// Returns an [`Iterator`] over each key-value pair in the component channel.
    pub fn iter(&self) -> impl Iterator<Item = (&'c K, &'c V)> {
        self.channel
            .iter()
            .flat_map(|c| c.iter())
    }
}

impl<'c, K, V> SystemParameter for QueryIndexed<'c, K, V>
    where
        K: Eq + Hash + 'static,
        V: 'static,
{
    fn fetch(cell: &UnsafeWorldCell) -> Self {
        let world = cell.get();
        let components = world.components();

        components.query_indexed::<K, V>()
    }
}

/// A mutable query against an indexed component set.
pub struct QueryIndexedMut<'c, TKey, TValue> {
    channel: Option<&'c mut ComponentMap<TKey, TValue>>,
}

impl<'c, TKey, TValue> QueryIndexedMut<'c, TKey, TValue>
    where
        TKey: Eq + Hash,
{
    /// Initializes [`self`] from an immutable reference to [`ComponentMap`].
    pub const fn from_channel(channel: Option<&'c mut ComponentMap<TKey, TValue>>) -> Self {
        Self { channel }
    }

    /// Gets an immutable reference to a component via it's key.
    pub fn get_mut(&'c mut self, key: &TKey) -> Option<&'c mut TValue> {
        self.channel
            .as_mut()
            .and_then(|c| c.get_mut(key))
    }

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

impl<'c, K, V> SystemParameter for QueryIndexedMut<'c, K, V>
    where
        K: Eq + Hash + 'static,
        V: 'static,
{
    fn fetch(cell: &UnsafeWorldCell) -> Self {
        let world = cell.get_mut();
        let components = world.components_mut();

        components.query_indexed_mut::<K, V>()
    }
}