checs 0.5.1

An Entity-Component-System library.
Documentation
//! Storing and managing components.

use crate::entity;
use crate::iter;
use crate::sparse;

/// A densely packed growable array for associating entities with components.
///
/// # Examples
///
/// ```
/// use checs::ComponentVec;
///
/// let mut entities = checs::entity::Allocator::new();
///
/// let e0 = entities.alloc();
/// let e1 = entities.alloc();
/// let e2 = entities.alloc();
/// let e3 = entities.alloc();
///
/// let mut vec = ComponentVec::new();
/// vec.insert(e0, 42);
/// vec.insert(e1, 17);
/// vec.insert(e2, 99);
/// assert_eq!(vec.len(), 3);
///
/// assert_eq!(vec.get(e0), Some(&42));
/// assert_eq!(vec.contains(e1), true);
/// assert_eq!(vec.get_mut(e2), Some(&mut 99));
/// assert_eq!(vec.get(e3), None);
///
/// assert_eq!(vec.remove(e2), Some(99));
/// assert_eq!(vec.get(e2), None);
///
/// for (entity, int) in &vec {
///     println!("{entity:?}: {int}");
/// }
/// ```
pub struct ComponentVec<T> {
    entities: sparse::Set,
    components: Vec<T>,
}

impl<T> ComponentVec<T> {
    /// Constructs a new empty `ComponentVec<T>`.
    ///
    /// The vector will not allocate until elements are pushed onto it.
    #[must_use]
    #[inline]
    pub fn new() -> Self {
        Self {
            components: Vec::new(),
            entities: sparse::Set::new(),
        }
    }

    /// Returns the number of elements in the vector, also referred to as its 'length'.
    #[must_use]
    #[inline]
    pub fn len(&self) -> usize {
        self.components.len()
    }

    /// Returns `true` if the vector contains no elements.
    #[must_use]
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.components.is_empty()
    }

    /// Returns `true` if the vector contains a component for the `entity`.
    #[must_use]
    #[inline]
    pub fn contains(&self, entity: entity::Entity) -> bool {
        self.entities.contains(entity)
    }

    /// Returns a reference to the `entity`'s component, or `None` if the entity does not have that
    /// component.
    #[must_use]
    #[inline]
    pub fn get(&self, entity: entity::Entity) -> Option<&T> {
        let index = self.entities.index_of(entity)?;
        self.components.get(index)
    }

    /// Returns a mutable reference to an `entity`'s component, or `None` if the `entity` does not
    /// have that component.
    #[must_use]
    #[inline]
    pub fn get_mut(&mut self, entity: entity::Entity) -> Option<&mut T> {
        let index = self.entities.index_of(entity)?;
        self.components.get_mut(index)
    }

    /// Adds a component to the `entity`.
    ///
    /// If the `entity` already had that component its value is updated and the old value is
    /// returned.
    #[inline]
    pub fn insert(&mut self, entity: entity::Entity, component: T) -> Option<T> {
        if let Some(value) = self.get_mut(entity) {
            Some(std::mem::replace(value, component))
        } else {
            self.entities.insert(entity);
            self.components.push(component);
            None
        }
    }

    /// Removes a component from the `entity` and returns the component.
    #[inline]
    pub fn remove(&mut self, entity: entity::Entity) -> Option<T> {
        if let Some(index) = self.entities.index_of(entity) {
            self.entities.remove(entity);
            Some(self.components.swap_remove(index))
        } else {
            None
        }
    }

    /// Reserves capacity for at least `additional` more elements to be inserted into the vector.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.entities.reserve(additional);
        self.components.reserve(additional);
    }

    /// Returns an iterator that yields entities and their components as references.
    #[inline]
    pub fn iter(&self) -> Iter<'_, T> {
        self.entities.iter().zip(self.components.iter())
    }

    /// Returns an iterator that yields entities and their components as mutable references.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
        self.entities.iter().zip(self.components.iter_mut())
    }
}

impl<T> Default for ComponentVec<T> {
    #[inline]
    fn default() -> ComponentVec<T> {
        ComponentVec::new()
    }
}

use std::iter::Zip;
use std::slice;

/// An iterator that yields entities and their components as references.
pub type Iter<'a, T> = Zip<iter::Iter<'a, entity::Entity>, slice::Iter<'a, T>>;

/// An iterator that yields entities and their components as mutable references.
pub type IterMut<'a, T> = Zip<iter::Iter<'a, entity::Entity>, slice::IterMut<'a, T>>;

impl<'a, T> IntoIterator for &'a ComponentVec<T> {
    type IntoIter = Iter<'a, T>;
    type Item = (entity::Entity, &'a T);

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, T> IntoIterator for &'a mut ComponentVec<T> {
    type IntoIter = IterMut<'a, T>;
    type Item = (entity::Entity, &'a mut T);

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

mod sealed {
    use super::ComponentVec;

    pub trait Sealed {}

    impl<T> Sealed for &ComponentVec<T> {}
    impl<T> Sealed for &mut ComponentVec<T> {}
}

use sealed::Sealed;

/// A reference to a [`ComponentVec`] that is generic over mutability.
///
/// # Note
///
/// This type is not meant to be used directly. It is used as part of a [`Query`], which is why it
/// must be public.
///
/// [`Query`]: crate::Query
pub struct RefOrMut<'a, T> {
    pub(crate) entities: &'a sparse::Set,
    components: T,
}

/// A trait for converting a value into a [`RefOrMut`].
pub trait IntoRefOrMut<'a>: Sealed {
    /// The type of slice containing the components. Either a shared or a mutable reference.
    type Components;

    /// Converts `self` into a [`RefOrMut`].
    fn into_ref_or_mut(self) -> RefOrMut<'a, Self::Components>;
}

impl<'a, T> IntoRefOrMut<'a> for &'a ComponentVec<T> {
    type Components = &'a [T];

    #[inline]
    fn into_ref_or_mut(self) -> RefOrMut<'a, Self::Components> {
        RefOrMut {
            entities: &self.entities,
            components: &self.components,
        }
    }
}

impl<'a, T> IntoRefOrMut<'a> for &'a mut ComponentVec<T> {
    type Components = &'a mut [T];

    #[inline]
    fn into_ref_or_mut(self) -> RefOrMut<'a, Self::Components> {
        RefOrMut {
            entities: &self.entities,
            components: &mut self.components,
        }
    }
}

impl<'l, 'a, T> iter::Lifetime<'l> for RefOrMut<'a, &'a [T]> {
    type Item = &'l T;
}

impl<'l, 'a, T> iter::Lifetime<'l> for RefOrMut<'a, &'a mut [T]> {
    type Item = &'l mut T;
}

/// A trait for returning a shared or mutable reference to a component.
pub trait GetRefOrMut: for<'l> iter::Lifetime<'l> {
    /// Returns a shared or mutable reference to an `entity`'s component, or `None` if the `entity`
    /// does not have that component.
    fn get_ref_or_mut(
        &mut self,
        entity: entity::Entity,
    ) -> Option<<Self as iter::Lifetime<'_>>::Item>;
}

impl<'a, T> GetRefOrMut for RefOrMut<'a, &'a [T]> {
    #[inline]
    fn get_ref_or_mut(
        &mut self,
        entity: entity::Entity,
    ) -> Option<<Self as iter::Lifetime<'_>>::Item> {
        let index = self.entities.index_of(entity)?;
        self.components.get(index)
    }
}

impl<'a, T> GetRefOrMut for RefOrMut<'a, &'a mut [T]> {
    #[inline]
    fn get_ref_or_mut(
        &mut self,
        entity: entity::Entity,
    ) -> Option<<Self as iter::Lifetime<'_>>::Item> {
        let index = self.entities.index_of(entity)?;
        self.components.get_mut(index)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn components_i32_put_then_delete() {
        let mut components = ComponentVec::new();

        let e0 = entity::Entity::from(0);
        let e1 = entity::Entity::from(1);

        components.insert(e0, 42);
        assert_eq!(components.components.len(), 1);

        components.insert(e1, 17);
        assert_eq!(components.components.len(), 2);

        assert_eq!(components.get(e0), Some(&42));
        assert_eq!(components.get(e1), Some(&17));
        assert_eq!(components.get_mut(e0), Some(&mut 42));
        assert_eq!(components.get_mut(e1), Some(&mut 17));

        components.remove(e0);
        assert_eq!(components.components.len(), 1);

        assert_eq!(components.get(e0), None);
        assert_eq!(components.get(e1), Some(&17));
        assert_eq!(components.get_mut(e0), None);
        assert_eq!(components.get_mut(e1), Some(&mut 17));

        components.remove(e1);
        assert_eq!(components.components.len(), 0);

        assert_eq!(components.get(e0), None);
        assert_eq!(components.get(e1), None);
        assert_eq!(components.get_mut(e0), None);
        assert_eq!(components.get_mut(e1), None);
    }

    #[test]
    fn reserve() {
        let mut vec = ComponentVec::<i32>::new();

        assert_eq!(vec.components.capacity(), 0);

        let additional = 100;
        vec.reserve(additional);

        assert!(vec.components.capacity() >= vec.components.len() + additional);
    }

    #[test]
    fn contains() {
        let mut components = ComponentVec::<i32>::new();

        let e0 = entity::Entity::from(0);
        let e1 = entity::Entity::from(1);
        let e2 = entity::Entity::from(2);

        components.insert(e0, 42);
        components.insert(e2, 17);

        assert_eq!(components.contains(e0), true);
        assert_eq!(components.contains(e1), false);
        assert_eq!(components.contains(e2), true);
    }
}