use std::iter;
use std::marker::PhantomData;
use crate::Archetype;
mod raw;
pub use raw::Raw;
pub mod deletion;
pub mod ealloc;
pub use ealloc::Ealloc;
pub mod generation;
pub use generation::Generation;
pub(crate) mod rctrack;
pub mod referrer;
pub use referrer::Referrer;
pub use crate::macros::EntityRef as Ref;
mod sealed {
pub trait Sealed {}
}
pub trait Ref: sealed::Sealed {
type Archetype: Archetype;
fn id(&self) -> <Self::Archetype as Archetype>::RawEntity;
}
#[repr(transparent)]
pub struct TempRef<'t, A: Archetype> {
value: A::RawEntity,
_ph: PhantomData<&'t ()>,
}
impl<'t, A: Archetype> TempRef<'t, A> {
pub(crate) fn new(value: A::RawEntity) -> Self { Self { value, _ph: PhantomData } }
}
impl<'t, A: Archetype> sealed::Sealed for TempRef<'t, A> {}
impl<'t, A: Archetype> Ref for TempRef<'t, A> {
type Archetype = A;
fn id(&self) -> A::RawEntity { self.value }
}
impl<'t, A: Archetype> Clone for TempRef<'t, A> {
fn clone(&self) -> Self { Self { value: self.value, _ph: PhantomData } }
}
impl<'t, A: Archetype> Copy for TempRef<'t, A> {}
pub struct TempRefChunk<'t, A: Archetype> {
pub(crate) start: A::RawEntity,
pub(crate) end: A::RawEntity,
pub(crate) _ph: PhantomData<&'t ()>,
}
impl<'t, A: Archetype> TempRefChunk<'t, A> {
pub fn iter(&self) -> impl Iterator<Item = TempRef<'t, A>> + '_ {
iter::successors(Some(self.start), |prev| {
Some(prev.add(1)).filter(|&value| value < self.end)
})
.map(|value| TempRef::new(value))
}
}
impl<'t, A: Archetype> Clone for TempRefChunk<'t, A> {
fn clone(&self) -> Self { Self { start: self.start, end: self.end, _ph: PhantomData } }
}
impl<'t, A: Archetype> Copy for TempRefChunk<'t, A> {}
#[cfg(any(
all(debug_assertions, feature = "debug-entity-rc"),
all(not(debug_assertions), feature = "release-entity-rc"),
))]
pub(crate) mod maybe {
use std::sync::{Arc, Weak};
pub(crate) type MaybeArc = Arc<()>;
pub(crate) type MaybeWeak = Weak<()>;
pub(crate) fn downgrade(arc: &MaybeArc) -> MaybeWeak { Arc::downgrade(arc) }
}
#[cfg(not(any(
all(debug_assertions, feature = "debug-entity-rc"),
all(not(debug_assertions), feature = "release-entity-rc"),
)))]
mod maybe {
#[derive(Clone, Default)]
pub(crate) struct MaybeArc;
#[derive(Clone)]
pub(crate) struct MaybeWeak;
#[allow(clippy::unused_unit)]
pub(crate) fn downgrade(&MaybeArc: &MaybeArc) -> MaybeWeak { MaybeWeak }
}
pub(crate) use maybe::{MaybeArc, MaybeWeak};
impl<'t, T: Ref> sealed::Sealed for &'t T {}
impl<'t, T: Ref> Ref for &'t T {
type Archetype = T::Archetype;
fn id(&self) -> <T::Archetype as Archetype>::RawEntity { Ref::id(&**self) }
}
pub struct Entity<A: Archetype> {
id: A::RawEntity,
pub(crate) rc: MaybeArc,
}
impl<A: Archetype> Entity<A> {
pub(crate) fn new_allocated(id: A::RawEntity) -> Self { Self { id, rc: MaybeArc::default() } }
pub fn weak(&self, store: &impl generation::WeakStore) -> Weak<A> {
let store = store
.resolve::<A>()
.expect("entity was instantiated without generation store initialized");
let generation = store.get(self.id.to_primitive());
Weak { id: self.id, generation, rc: maybe::downgrade(&self.rc) }
}
}
impl<A: Archetype> sealed::Sealed for Entity<A> {}
impl<A: Archetype> Ref for Entity<A> {
type Archetype = A;
fn id(&self) -> A::RawEntity { self.id }
}
impl<A: Archetype> Clone for Entity<A> {
fn clone(&self) -> Self {
Self {
id: self.id,
rc: Clone::clone(&self.rc),
}
}
}
pub struct Weak<A: Archetype> {
id: A::RawEntity,
generation: Generation,
rc: maybe::MaybeWeak,
}
impl<A: Archetype> sealed::Sealed for Weak<A> {}
impl<A: Archetype> Ref for Weak<A> {
type Archetype = A;
fn id(&self) -> A::RawEntity { self.id }
}
impl<A: Archetype> Clone for Weak<A> {
fn clone(&self) -> Self {
Self {
id: self.id,
generation: self.generation,
rc: Clone::clone(&self.rc),
}
}
}
#[cfg(test)]
mod tests;