use std::any::{Any, TypeId};
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use serde::{Deserialize, Serialize};
use super::entity_store::get_entity_metadata_static;
#[derive(Serialize, Deserialize)]
#[serde(transparent)]
pub struct EntityId<E: Entity>(pub(crate) usize, PhantomData<E>);
impl<E: Entity> PartialEq for EntityId<E> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<E: Entity> Eq for EntityId<E> {}
impl<E: Entity> Clone for EntityId<E> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<E: Entity> Copy for EntityId<E> {}
impl<E: Entity> Debug for EntityId<E> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let name = format!("{}Id", E::name());
f.debug_tuple(name.as_str()).field(&self.0).finish()
}
}
impl<E: Entity> Display for EntityId<E> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl<E: Entity> Hash for EntityId<E> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<E: Entity> EntityId<E> {
pub(crate) fn new(index: usize) -> Self {
Self(index, PhantomData)
}
}
pub trait Entity: Any + Default {
fn name() -> &'static str {
let full = std::any::type_name::<Self>();
full.rsplit("::").next().unwrap()
}
fn type_id() -> TypeId {
TypeId::of::<Self>()
}
fn property_ids() -> &'static [TypeId] {
let (property_ids, _) = get_entity_metadata_static(<Self as Entity>::type_id());
property_ids
}
fn required_property_ids() -> &'static [TypeId] {
let (_, required_property_ids) = get_entity_metadata_static(<Self as Entity>::type_id());
required_property_ids
}
fn id() -> usize;
fn new_boxed() -> Box<Self> {
Box::default()
}
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
pub type BxEntity = Box<dyn Entity>;
#[derive(Copy, Clone)]
pub struct PopulationIterator<E: Entity> {
population: usize,
entity_id: usize,
_phantom: PhantomData<E>,
}
impl<E: Entity> PopulationIterator<E> {
pub(crate) fn new(population: usize) -> Self {
PopulationIterator::<E> {
population,
entity_id: 0,
_phantom: PhantomData,
}
}
#[must_use]
pub(crate) fn population(&self) -> usize {
self.population
}
}
impl<E: Entity> Iterator for PopulationIterator<E> {
type Item = EntityId<E>;
fn next(&mut self) -> Option<Self::Item> {
if self.entity_id < self.population {
let current_id = self.entity_id;
self.entity_id += 1;
Some(EntityId::new(current_id))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.len();
(remaining, Some(remaining))
}
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.entity_id = (self.entity_id + n).min(self.population);
self.next()
}
}
impl<E: Entity> ExactSizeIterator for PopulationIterator<E> {
fn len(&self) -> usize {
self.population - self.entity_id
}
}
impl<E: Entity> std::iter::FusedIterator for PopulationIterator<E> {}
#[cfg(test)]
mod tests {
use super::*;
use crate::define_entity;
define_entity!(DummyEntity);
#[test]
fn entity_id_debug_display() {
let entity_id = DummyEntityId::new(137);
assert_eq!(format!("{:?}", entity_id), "DummyEntityId(137)");
assert_eq!(format!("{}", entity_id), "137");
}
#[test]
fn test_entity_iterator_basic() {
let mut iter = PopulationIterator::<DummyEntity>::new(3);
assert_eq!(iter.len(), 3);
assert_eq!(iter.next(), Some(EntityId::new(0)));
assert_eq!(iter.len(), 2);
assert_eq!(iter.next(), Some(EntityId::new(1)));
assert_eq!(iter.len(), 1);
assert_eq!(iter.next(), Some(EntityId::new(2)));
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None); }
#[test]
fn test_entity_iterator_nth() {
let mut iter = PopulationIterator::<DummyEntity>::new(10);
assert_eq!(iter.nth(2), Some(EntityId::new(2)));
assert_eq!(iter.len(), 7);
assert_eq!(iter.nth(1), Some(EntityId::new(4)));
assert_eq!(iter.nth(10), None);
assert_eq!(iter.len(), 0);
assert_eq!(iter.next(), None);
}
#[test]
fn test_entity_iterator_size_hint() {
let mut iter = PopulationIterator::<DummyEntity>::new(5);
assert_eq!(iter.size_hint(), (5, Some(5)));
iter.next();
assert_eq!(iter.size_hint(), (4, Some(4)));
assert_eq!(iter.nth(10), None);
assert_eq!(iter.size_hint(), (0, Some(0)));
}
#[test]
fn test_entity_iterator_clonable() {
let mut iter = PopulationIterator::<DummyEntity>::new(5);
iter.next();
let mut cloned = iter;
assert_eq!(iter.next(), cloned.next());
assert_eq!(iter.size_hint(), cloned.size_hint());
}
}