use core::any::TypeId;
use core::fmt::{self, Debug, Display, Formatter};
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut, FnOnce};
use core::ptr::NonNull;
use crate::archetype::Archetype;
use crate::entities::EntityMeta;
use crate::{
ArchetypeColumn, ArchetypeColumnMut, Component, Entity, Fetch, MissingComponent, Query,
QueryOne,
};
#[derive(Copy, Clone)]
pub struct EntityRef<'a> {
meta: &'a [EntityMeta],
archetype: &'a Archetype,
index: u32,
}
impl<'a> EntityRef<'a> {
pub(crate) unsafe fn new(meta: &'a [EntityMeta], archetype: &'a Archetype, index: u32) -> Self {
Self {
meta,
archetype,
index,
}
}
#[inline]
pub fn entity(&self) -> Entity {
let id = self.archetype.entity_id(self.index);
Entity {
id,
generation: self.meta[id as usize].generation,
}
}
pub fn satisfies<Q: Query>(&self) -> bool {
Q::Fetch::access(self.archetype).is_some()
}
pub fn has<T: Component>(&self) -> bool {
self.archetype.has::<T>()
}
pub fn get<T: ComponentRef<'a>>(&self) -> Option<T::Ref> {
T::get_component(*self)
}
pub fn query<Q: Query>(&self) -> QueryOne<'a, Q> {
unsafe { QueryOne::new(self.meta, self.archetype, self.index) }
}
pub fn component_types(&self) -> impl Iterator<Item = TypeId> + 'a {
self.archetype.types().iter().map(|ty| ty.id())
}
pub fn len(&self) -> usize {
self.archetype.types().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
unsafe impl Send for EntityRef<'_> {}
unsafe impl Sync for EntityRef<'_> {}
pub struct Ref<'a, T: ?Sized> {
borrow: ComponentBorrow<'a>,
target: NonNull<T>,
_phantom: PhantomData<&'a T>,
}
impl<'a, T: Component> Ref<'a, T> {
pub(crate) unsafe fn new(
archetype: &'a Archetype,
index: u32,
) -> Result<Self, MissingComponent> {
let (target, borrow) = ComponentBorrow::for_component::<T>(archetype, index)?;
Ok(Self {
borrow,
target,
_phantom: PhantomData,
})
}
}
unsafe impl<T: ?Sized + Sync> Send for Ref<'_, T> {}
unsafe impl<T: ?Sized + Sync> Sync for Ref<'_, T> {}
impl<'a, T: ?Sized> Ref<'a, T> {
pub fn map<U: ?Sized, F>(orig: Ref<'a, T>, f: F) -> Ref<'a, U>
where
F: FnOnce(&T) -> &U,
{
let target = NonNull::from(f(&*orig));
Ref {
borrow: orig.borrow,
target,
_phantom: PhantomData,
}
}
}
impl<T: ?Sized> Deref for Ref<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.target.as_ref() }
}
}
impl<T: ?Sized + Debug> Debug for Ref<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.deref(), f)
}
}
impl<T: ?Sized + Display> Display for Ref<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(self.deref(), f)
}
}
impl<T: ?Sized> Clone for Ref<'_, T> {
fn clone(&self) -> Self {
Self {
borrow: self.borrow.clone(),
target: self.target,
_phantom: self._phantom,
}
}
}
pub struct RefMut<'a, T: ?Sized> {
borrow: ComponentBorrowMut<'a>,
target: NonNull<T>,
_phantom: PhantomData<&'a mut T>,
}
impl<'a, T: Component> RefMut<'a, T> {
pub(crate) unsafe fn new(
archetype: &'a Archetype,
index: u32,
) -> Result<Self, MissingComponent> {
let (target, borrow) = ComponentBorrowMut::for_component::<T>(archetype, index)?;
Ok(Self {
borrow,
target,
_phantom: PhantomData,
})
}
}
unsafe impl<T: ?Sized + Send> Send for RefMut<'_, T> {}
unsafe impl<T: ?Sized + Sync> Sync for RefMut<'_, T> {}
impl<'a, T: ?Sized> RefMut<'a, T> {
pub fn map<U: ?Sized, F>(mut orig: RefMut<'a, T>, f: F) -> RefMut<'a, U>
where
F: FnOnce(&mut T) -> &mut U,
{
let target = NonNull::from(f(&mut *orig));
RefMut {
borrow: orig.borrow,
target,
_phantom: PhantomData,
}
}
}
impl<T: ?Sized> Deref for RefMut<'_, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.target.as_ref() }
}
}
impl<T: ?Sized> DerefMut for RefMut<'_, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { self.target.as_mut() }
}
}
impl<T: ?Sized + Debug> Debug for RefMut<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.deref(), f)
}
}
impl<T: ?Sized + Display> Display for RefMut<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(self.deref(), f)
}
}
pub trait ComponentRef<'a> {
#[doc(hidden)]
type Ref;
#[doc(hidden)]
type Column;
#[doc(hidden)]
type Component: Component;
#[doc(hidden)]
fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref>;
#[doc(hidden)]
unsafe fn from_raw(raw: *mut Self::Component) -> Self;
#[doc(hidden)]
fn get_column(archetype: &'a Archetype) -> Option<Self::Column>;
}
impl<'a, T: Component> ComponentRef<'a> for &'a T {
type Ref = Ref<'a, T>;
type Column = ArchetypeColumn<'a, T>;
type Component = T;
fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref> {
Some(unsafe { Ref::new(entity.archetype, entity.index).ok()? })
}
unsafe fn from_raw(raw: *mut Self::Component) -> Self {
&*raw
}
fn get_column(archetype: &'a Archetype) -> Option<Self::Column> {
ArchetypeColumn::new(archetype)
}
}
impl<'a, T: Component> ComponentRef<'a> for &'a mut T {
type Ref = RefMut<'a, T>;
type Column = ArchetypeColumnMut<'a, T>;
type Component = T;
fn get_component(entity: EntityRef<'a>) -> Option<Self::Ref> {
Some(unsafe { RefMut::new(entity.archetype, entity.index).ok()? })
}
unsafe fn from_raw(raw: *mut Self::Component) -> Self {
&mut *raw
}
fn get_column(archetype: &'a Archetype) -> Option<Self::Column> {
ArchetypeColumnMut::new(archetype)
}
}
pub trait ComponentRefShared<'a>: ComponentRef<'a> {}
impl<'a, T: Component> ComponentRefShared<'a> for &'a T {}
struct ComponentBorrow<'a> {
archetype: &'a Archetype,
state: usize,
}
impl<'a> ComponentBorrow<'a> {
unsafe fn for_component<T: Component>(
archetype: &'a Archetype,
index: u32,
) -> Result<(NonNull<T>, Self), MissingComponent> {
let state = archetype
.get_state::<T>()
.ok_or_else(MissingComponent::new::<T>)?;
let target =
NonNull::new_unchecked(archetype.get_base::<T>(state).as_ptr().add(index as usize));
archetype.borrow::<T>(state);
Ok((target, Self { archetype, state }))
}
}
impl Clone for ComponentBorrow<'_> {
fn clone(&self) -> Self {
unsafe {
self.archetype.borrow_raw(self.state);
}
Self {
archetype: self.archetype,
state: self.state,
}
}
}
impl Drop for ComponentBorrow<'_> {
fn drop(&mut self) {
unsafe {
self.archetype.release_raw(self.state);
}
}
}
struct ComponentBorrowMut<'a> {
archetype: &'a Archetype,
state: usize,
}
impl<'a> ComponentBorrowMut<'a> {
unsafe fn for_component<T: Component>(
archetype: &'a Archetype,
index: u32,
) -> Result<(NonNull<T>, Self), MissingComponent> {
let state = archetype
.get_state::<T>()
.ok_or_else(MissingComponent::new::<T>)?;
let target =
NonNull::new_unchecked(archetype.get_base::<T>(state).as_ptr().add(index as usize));
archetype.borrow_mut::<T>(state);
Ok((target, Self { archetype, state }))
}
}
impl Drop for ComponentBorrowMut<'_> {
fn drop(&mut self) {
unsafe {
self.archetype.release_raw_mut(self.state);
}
}
}