use std::{marker::PhantomData, rc::Rc};
use crate::prelude::*;
use super::untyped::UntypedComponentStore;
#[derive(Clone)]
#[repr(transparent)]
pub struct ComponentStore<T: HasSchema> {
untyped: UntypedComponentStore,
_phantom: PhantomData<T>,
}
impl<T: HasSchema> Default for ComponentStore<T> {
fn default() -> Self {
Self {
untyped: UntypedComponentStore::for_type::<T>(),
_phantom: PhantomData,
}
}
}
impl<T: HasSchema> TryFrom<UntypedComponentStore> for ComponentStore<T> {
type Error = SchemaMismatchError;
fn try_from(untyped: UntypedComponentStore) -> Result<Self, Self::Error> {
if untyped.schema == T::schema() {
Ok(Self {
untyped,
_phantom: PhantomData,
})
} else {
Err(SchemaMismatchError)
}
}
}
impl<T: HasSchema> ComponentStore<T> {
#[inline]
pub fn into_untyped(self) -> UntypedComponentStore {
self.untyped
}
#[track_caller]
pub fn from_untyped(untyped: UntypedComponentStore) -> Self {
untyped.try_into().unwrap()
}
#[inline]
pub fn insert(&mut self, entity: Entity, component: T) -> Option<T> {
self.untyped.insert(entity, component)
}
#[inline]
pub fn get(&self, entity: Entity) -> Option<&T> {
self.untyped.get(entity)
}
#[inline]
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
self.untyped.get_mut(entity)
}
#[inline]
pub fn get_mut_or_insert(&mut self, entity: Entity, f: impl FnOnce() -> T) -> &mut T {
self.untyped.get_mut_or_insert(entity, f)
}
#[track_caller]
pub fn get_many_mut<const N: usize>(&mut self, entities: [Entity; N]) -> [Option<&mut T>; N] {
let mut result = self.untyped.get_many_ref_mut(entities);
std::array::from_fn(move |i| {
result[i]
.take()
.map(|x| unsafe { x.cast_into_mut_unchecked() })
})
}
#[inline]
pub fn remove(&mut self, entity: Entity) -> Option<T> {
self.untyped.remove(entity)
}
#[inline]
pub fn get_single_with_bitset(&self, bitset: Rc<BitSetVec>) -> Result<&T, QuerySingleError> {
self.untyped
.get_single_with_bitset(bitset)
.map(|x| unsafe { x.cast_into_unchecked() })
}
#[inline]
pub fn get_single_with_bitset_mut(
&mut self,
bitset: Rc<BitSetVec>,
) -> Result<&mut T, QuerySingleError> {
self.untyped
.get_single_with_bitset_mut(bitset)
.map(|x| unsafe { x.cast_into_mut_unchecked() })
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.untyped
.iter()
.map(|x| unsafe { x.cast_into_unchecked() })
}
#[inline]
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.untyped
.iter_mut()
.map(|x| unsafe { x.cast_into_mut_unchecked() })
}
}
pub trait ComponentIterBitset<'a, T: HasSchema> {
fn get_single_with_bitset(&self, bitset: Rc<BitSetVec>) -> Result<&T, QuerySingleError>;
fn get_single_mut_with_bitset(
&mut self,
bitset: Rc<BitSetVec>,
) -> Result<&mut T, QuerySingleError>;
fn iter_with_bitset(&self, bitset: Rc<BitSetVec>) -> ComponentBitsetIterator<T>;
fn iter_with_bitset_optional(
&self,
bitset: Rc<BitSetVec>,
) -> ComponentBitsetOptionalIterator<T>;
fn iter_mut_with_bitset(&mut self, bitset: Rc<BitSetVec>) -> ComponentBitsetIteratorMut<T>;
fn iter_mut_with_bitset_optional(
&mut self,
bitset: Rc<BitSetVec>,
) -> ComponentBitsetOptionalIteratorMut<T>;
fn bitset(&self) -> &BitSetVec;
fn contains(&self, entity: Entity) -> bool;
fn component_store(&self) -> &ComponentStore<T>;
}
impl<'a, T: HasSchema> ComponentIterBitset<'a, T> for ComponentStore<T> {
fn get_single_with_bitset(&self, bitset: Rc<BitSetVec>) -> Result<&T, QuerySingleError> {
fn map<T>(r: SchemaRef) -> &T {
unsafe { r.cast_into_unchecked() }
}
self.untyped.get_single_with_bitset(bitset).map(map)
}
fn get_single_mut_with_bitset(
&mut self,
bitset: Rc<BitSetVec>,
) -> Result<&mut T, QuerySingleError> {
fn map<T>(r: SchemaRefMut) -> &mut T {
unsafe { r.cast_into_mut_unchecked() }
}
self.untyped.get_single_with_bitset_mut(bitset).map(map)
}
#[inline]
fn iter_with_bitset(&self, bitset: Rc<BitSetVec>) -> ComponentBitsetIterator<T> {
fn map<T>(r: SchemaRef) -> &T {
unsafe { r.cast_into_unchecked() }
}
self.untyped.iter_with_bitset(bitset).map(map)
}
#[inline]
fn iter_with_bitset_optional(
&self,
bitset: Rc<BitSetVec>,
) -> ComponentBitsetOptionalIterator<T> {
fn map<T>(r: Option<SchemaRef>) -> Option<&T> {
r.map(|r| unsafe { r.cast_into_unchecked() })
}
self.untyped.iter_with_bitset_optional(bitset).map(map)
}
#[inline]
fn iter_mut_with_bitset(&mut self, bitset: Rc<BitSetVec>) -> ComponentBitsetIteratorMut<T> {
fn map<T>(r: SchemaRefMut) -> &mut T {
unsafe { r.cast_into_mut_unchecked() }
}
self.untyped.iter_mut_with_bitset(bitset).map(map)
}
#[inline]
fn iter_mut_with_bitset_optional(
&mut self,
bitset: Rc<BitSetVec>,
) -> ComponentBitsetOptionalIteratorMut<T> {
fn map<T>(r: Option<SchemaRefMut>) -> Option<&mut T> {
r.map(|r| unsafe { r.cast_into_mut_unchecked() })
}
self.untyped.iter_mut_with_bitset_optional(bitset).map(map)
}
#[inline]
fn bitset(&self) -> &BitSetVec {
self.untyped.bitset()
}
#[inline]
fn contains(&self, entity: Entity) -> bool {
self.bitset().contains(entity)
}
#[inline]
fn component_store(&self) -> &ComponentStore<T> {
self
}
}
#[cfg(test)]
mod tests {
#![allow(non_snake_case)]
use std::{iter, rc::Rc};
use crate::prelude::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, HasSchema, Default)]
#[repr(C)]
struct A(u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, HasSchema, Default)]
#[repr(C)]
struct B(u32);
fn entity(index: u32) -> Entity {
Entity::new(index, 0)
}
fn store(entities: &[u32]) -> ComponentStore<A> {
let mut store = ComponentStore::default();
for &i in entities {
store.insert(entity(i), A(i));
}
store
}
fn bitset(enabled: &[usize]) -> Rc<BitSetVec> {
let mut bitset = BitSetVec::default();
for &i in enabled {
bitset.bit_set(i);
}
Rc::new(bitset)
}
#[test]
fn create_remove_components() {
let mut entities = Entities::default();
let e1 = entities.create();
let e2 = entities.create();
let mut storage = ComponentStore::<A>::default();
storage.insert(e1, A(1));
storage.insert(e2, A(2));
assert!(storage.get(e1).is_some());
storage.remove(e1);
assert!(storage.get(e1).is_none());
assert!(storage.iter().eq(iter::once(&A(2))));
}
#[test]
fn get_mut_or_insert() {
let mut entities = Entities::default();
let e1 = entities.create();
let mut storage = ComponentStore::<A>::default();
{
let comp = storage.get_mut_or_insert(e1, || A(1));
assert_eq!(comp.0, 1);
comp.0 = 2;
}
let comp = storage.get_mut_or_insert(e1, || A(u32::MAX));
assert_eq!(comp.0, 2);
}
#[test]
fn iter() {
let mut store = store(&[10, 20, 30]);
let expected = vec![10, 20, 30];
let actual = store.iter().map(|c| c.0).collect::<Vec<_>>();
assert_eq!(actual, expected);
let actual = store.iter_mut().map(|c| c.0).collect::<Vec<_>>();
assert_eq!(actual, expected);
}
#[test]
fn get_single_with_bitset() {
{
let (mut store, bitset) = (store(&[]), bitset(&[]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::NoEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::NoEntities));
}
{
let (mut store, bitset) = (store(&[1]), bitset(&[]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::NoEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::NoEntities));
}
{
let (mut store, bitset) = (store(&[]), bitset(&[1]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::NoEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::NoEntities));
}
{
let (mut store, bitset) = (store(&[3]), bitset(&[3]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Ok(&A(3)));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Ok(&mut A(3)));
}
{
let (mut store, bitset) = (store(&[5, 6]), bitset(&[5, 6]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::MultipleEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::MultipleEntities));
}
{
let (mut store, bitset) = (store(&[11, 21, 31]), bitset(&[12, 22, 32]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::NoEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::NoEntities));
}
{
let (mut store, bitset) = (store(&[11, 20, 31, 41]), bitset(&[12, 20, 32, 42]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Ok(&A(20)));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Ok(&mut A(20)));
}
{
let (mut store, bitset) = (store(&[11, 21, 30, 41, 50]), bitset(&[12, 22, 30, 42, 50]));
let result = store.get_single_with_bitset(bitset.clone());
assert_eq!(result, Err(QuerySingleError::MultipleEntities));
let result = store.get_single_with_bitset_mut(bitset);
assert_eq!(result, Err(QuerySingleError::MultipleEntities));
}
}
#[test]
fn iter_with_bitset() {
{
let (mut store, bitset) = (store(&[]), bitset(&[]));
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset);
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[]), bitset(&[10, 20]));
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset);
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[10, 20]), bitset(&[]));
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset);
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[11, 21, 31]), bitset(&[12, 22, 32]));
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset.clone());
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[5]), bitset(&[5]));
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), Some(&A(5)));
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset);
assert_eq!(iter.next(), Some(&mut A(5)));
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (
store(&[11, 20, 31, 41, 50, 61]),
bitset(&[12, 20, 32, 42, 50, 62]),
);
let mut iter = store.iter_with_bitset(bitset.clone());
assert_eq!(iter.next(), Some(&A(20)));
assert_eq!(iter.next(), Some(&A(50)));
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset(bitset);
assert_eq!(iter.next(), Some(&mut A(20)));
assert_eq!(iter.next(), Some(&mut A(50)));
assert_eq!(iter.next(), None);
}
}
#[test]
fn iter_with_bitset_optional() {
{
let (mut store, bitset) = (store(&[]), bitset(&[]));
let mut iter = store.iter_with_bitset_optional(bitset.clone());
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset_optional(bitset);
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[]), bitset(&[5, 6]));
let mut iter = store.iter_with_bitset_optional(bitset.clone());
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset_optional(bitset);
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[11, 21, 31]), bitset(&[12, 22, 32]));
let mut iter = store.iter_with_bitset_optional(bitset.clone());
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset_optional(bitset);
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
}
{
let (mut store, bitset) = (store(&[11, 20, 31]), bitset(&[12, 20, 32]));
let mut iter = store.iter_with_bitset_optional(bitset.clone());
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(Some(&A(20))));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
let mut iter = store.iter_mut_with_bitset_optional(bitset);
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), Some(Some(&mut A(20))));
assert_eq!(iter.next(), Some(None));
assert_eq!(iter.next(), None);
}
}
}