use crate::component::{Component, ComponentSparseSet};
use crate::entity::{Entity, SparseVec};
use atomic_refcell::{AtomicRef, AtomicRefMut};
use core::fmt;
use core::marker::PhantomData;
use core::ops::{Index, IndexMut};
use core::ptr::NonNull;
pub struct View<'a, T> {
components: AtomicRef<'a, ComponentSparseSet>,
_phantom: PhantomData<&'a [T]>,
}
impl<'a, T> View<'a, T> {
#[inline]
#[must_use]
pub(crate) fn new(components: AtomicRef<'a, ComponentSparseSet>) -> Self {
Self {
components,
_phantom: PhantomData,
}
}
}
pub struct ViewMut<'a, T> {
components: AtomicRefMut<'a, ComponentSparseSet>,
_phantom: PhantomData<&'a mut [T]>,
}
impl<'a, T> ViewMut<'a, T>
where
T: Component,
{
#[inline]
#[must_use]
pub(crate) fn new(components: AtomicRefMut<'a, ComponentSparseSet>) -> Self {
Self {
components,
_phantom: PhantomData,
}
}
#[must_use]
pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> {
unsafe { self.components.get_mut::<T>(entity) }
}
#[must_use]
pub fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { self.components.as_mut_slice::<T>() }
}
}
impl<T> IndexMut<Entity> for ViewMut<'_, T>
where
T: Component,
{
fn index_mut(&mut self, entity: Entity) -> &mut Self::Output {
self.get_mut(entity).unwrap()
}
}
macro_rules! impl_view_common {
($View:ident) => {
impl<'a, T> $View<'a, T>
where
T: Component,
{
#[must_use]
pub fn get(&self, entity: Entity) -> Option<&T> {
unsafe { self.components.get::<T>(entity) }
}
#[must_use]
pub fn contains(&self, entity: Entity) -> bool {
self.components.contains(entity)
}
#[must_use]
pub fn len(&self) -> usize {
self.components.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.components.is_empty()
}
#[must_use]
pub fn entities(&self) -> &[Entity] {
self.components.entities()
}
#[must_use]
pub fn as_slice(&self) -> &[T] {
unsafe { self.components.as_slice::<T>() }
}
#[must_use]
pub(crate) fn sparse(&self) -> &SparseVec {
self.components.sparse()
}
#[must_use]
pub(crate) fn as_non_null_ptr(&self) -> NonNull<T> {
unsafe { self.components.as_non_null_ptr::<T>() }
}
}
impl<T> Index<Entity> for $View<'_, T>
where
T: Component,
{
type Output = T;
fn index(&self, entity: Entity) -> &Self::Output {
self.get(entity).unwrap()
}
}
impl<T> fmt::Debug for $View<'_, T>
where
T: Component + fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entries = self.entities().iter().zip(self.as_slice());
f.debug_map().entries(entries).finish()
}
}
};
}
impl_view_common!(View);
impl_view_common!(ViewMut);