extern crate downcast_rs;
extern crate itertools;
extern crate log;
extern crate parking_lot;
extern crate rayon;
extern crate typedef;
extern crate vec_map;
use downcast_rs::{impl_downcast, Downcast};
use itertools::{multizip, Zip};
use log::debug;
use parking_lot::Mutex;
use std::any::TypeId;
use std::cell::UnsafeCell;
use std::collections::{HashMap, HashSet};
use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::num::Wrapping;
use typedef::TypeDef;
use vec_map::VecMap;
pub type StorageId = u16;
pub type ComponentId = u32;
pub type Version = u16;
pub struct BorrowIter<'s, S, I> {
world: &'s World<S>,
iter: I,
}
impl<'s, S, I> Iterator for BorrowIter<'s, S, I>
where
I: Iterator,
{
type Item = I::Item;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<'s, S, I> FusedIterator for BorrowIter<'s, S, I> where I: FusedIterator {}
impl<'s, S, I> ExactSizeIterator for BorrowIter<'s, S, I>
where
I: ExactSizeIterator,
{
fn len(&self) -> usize {
self.iter.len()
}
}
impl<'s, S, I> Drop for BorrowIter<'s, S, I> {
fn drop(&mut self) {
self.world.runtime_borrow.lock().pop_access();
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct Entity {
version: Wrapping<Version>,
storage_id: StorageId,
id: ComponentId,
}
pub struct World<S = SoaStorage> {
component_map: Vec<VecMap<ComponentId>>,
component_map_inv: Vec<VecMap<ComponentId>>,
free_map: Vec<Vec<ComponentId>>,
version: Vec<Vec<Wrapping<Version>>>,
storages: Vec<S>,
runtime_borrow: Mutex<RuntimeBorrow>,
}
impl<S> Default for World<S> {
fn default() -> Self {
Self::new()
}
}
impl<S> World<S> {
pub fn new() -> Self {
World {
runtime_borrow: Mutex::new(RuntimeBorrow::new()),
component_map: Vec::new(),
component_map_inv: Vec::new(),
free_map: Vec::new(),
version: Vec::new(),
storages: Vec::new(),
}
}
}
impl<S> World<S>
where
S: Storage,
{
pub fn entities<'s>(&'s self) -> impl Iterator<Item = Entity> + 's {
self.component_map
.iter()
.enumerate()
.flat_map(move |(idx, inner)| {
let storage_id = idx as StorageId;
inner.keys().map(move |component_id| Entity {
storage_id,
id: component_id as ComponentId,
version: self.version[storage_id as usize][component_id as usize],
})
})
}
fn entities_storage<'s>(&'s self, storage_id: StorageId) -> impl Iterator<Item = Entity> + 's {
self.component_map_inv[storage_id as usize]
.values()
.map(move |&id| Entity {
storage_id,
id,
version: self.version[storage_id as usize][id as usize],
})
}
fn borrow_and_validate<Borrow: RegisterBorrow>(&self) {
let mut borrow = self.runtime_borrow.lock();
borrow.push_access::<Borrow>();
if let Err(overlapping_borrows) = borrow.validate() {
panic!("Detected multiple active borrows of: {:?}", {
overlapping_borrows
.iter()
.map(|ty| ty.get_str())
.collect::<Vec<_>>()
});
}
}
pub fn matcher<'s, Q>(
&'s self,
) -> impl Iterator<Item = <<Q as Query<'s>>::Iter as Iterator>::Item> + 's
where
Q: Query<'s> + Matcher,
Q::Borrow: RegisterBorrow,
{
self.borrow_and_validate::<Q::Borrow>();
let iter = unsafe {
self.storages
.iter()
.filter(|&storage| Q::is_match(storage))
.map(|storage| Q::query(storage))
.flat_map(|iter| iter)
};
BorrowIter { world: self, iter }
}
pub fn matcher_with_entities<'s, Q>(
&'s self,
) -> impl Iterator<Item = (Entity, <<Q as Query<'s>>::Iter as Iterator>::Item)> + 's
where
Q: Query<'s> + Matcher,
Q::Borrow: RegisterBorrow,
{
self.borrow_and_validate::<Q::Borrow>();
let iter = self
.storages
.iter()
.enumerate()
.filter(|&(_, storage)| Q::is_match(storage))
.flat_map(move |(id, storage)| {
let query = unsafe { Q::query(storage) };
let entities = self.entities_storage(id as StorageId);
Iterator::zip(entities, query)
});
BorrowIter { world: self, iter }
}
}
impl<S> World<S>
where
S: Storage + RegisterComponent,
{
pub fn append_components<A, I>(&mut self, i: I)
where
A: AppendComponents + BuildStorage,
I: IntoIterator<Item = A>,
{
let (storage_id, insert_count) = if let Some(storage) = self
.storages
.iter_mut()
.find(|storage| A::is_match::<S>(storage))
{
let len = A::append_components(i, storage);
(storage.id(), len)
} else {
let id = self.storages.len() as StorageId;
let mut storage = <A as BuildStorage>::build::<S>(id).access();
let len = A::append_components(i, &mut storage);
self.storages.push(storage);
self.component_map.push(VecMap::default());
self.component_map_inv.push(VecMap::default());
self.free_map.push(Vec::new());
self.version.push(Vec::new());
(id, len)
};
let storage_index = storage_id as usize;
if insert_count == 0 {
return;
}
let start_len = self.component_map[storage_index].len() as ComponentId;
let end_len = start_len + insert_count as ComponentId;
debug!("Append to Storage: {}", storage_id);
debug!("- Insert count: {}", insert_count);
debug!(
"- Map length before: {}",
self.component_map[storage_id as usize].len()
);
for component_id in start_len..end_len {
if let Some(insert_at) = self.free_map[storage_index].pop() {
self.insert_component_map(storage_id, insert_at, component_id);
} else {
let insert_at = self.component_map[storage_index].len() as ComponentId;
self.version[storage_index].push(Wrapping(0));
self.insert_component_map(storage_id, insert_at, component_id);
}
}
assert_eq!(
self.component_map[storage_index].len(),
self.storages[storage_index].len(),
"The size of the component map and storage map should be equal"
);
}
pub fn is_entity_valid(&self, entity: Entity) -> bool {
self.version[entity.storage_id as usize]
.get(entity.id as usize)
.map(|&version| version == entity.version)
.unwrap_or(false)
}
fn insert_component_map(
&mut self,
storage_id: StorageId,
id: ComponentId,
component_id: ComponentId,
) {
self.component_map[storage_id as usize].insert(id as usize, component_id);
self.component_map_inv[storage_id as usize].insert(component_id as usize, id);
}
pub fn has_component<C: Component>(&self, e: Entity) -> bool {
self.get_component::<C>(e).is_some()
}
pub fn get_component<C: Component>(&self, e: Entity) -> Option<&C> {
unsafe {
let storage = &self.storages[e.storage_id as usize];
if !storage.contains::<C>() || !self.is_entity_valid(e) {
return None;
}
let component_id = self.component_map[e.storage_id as usize][e.id as usize];
storage.component::<C>().get(component_id as usize)
}
}
pub fn get_component_mut<C: Component>(&mut self, e: Entity) -> Option<&mut C> {
unsafe {
let storage = &self.storages[e.storage_id as usize];
if !storage.contains::<C>() || !self.is_entity_valid(e) {
return None;
}
let component_id = self.component_map[e.storage_id as usize][e.id as usize];
storage.component_mut::<C>().get_mut(component_id as usize)
}
}
pub fn remove_entities<I>(&mut self, entities: I)
where
I: IntoIterator<Item = Entity>,
{
for entity in entities {
debug!("Removing {:?}", entity);
let storage_id = entity.storage_id as usize;
let is_valid = self.is_entity_valid(entity);
if !is_valid {
continue;
}
let component_id = *self.component_map[storage_id]
.get(entity.id as usize)
.expect("component id");
let swap = self.storages[storage_id].remove(component_id) as ComponentId;
debug!(
"- Entitiy id: {}, Component id: {}, Swap: {}, Map length: {}, Storage length: {}",
entity.id,
component_id,
swap,
self.storages[storage_id].len() + 1,
self.component_map[storage_id].len()
);
let key = self.component_map_inv[storage_id][swap as usize];
debug!("- Updating {} to {}", key, component_id);
self.insert_component_map(storage_id as StorageId, key, component_id);
debug!("- Removing {} from `component_map`", entity.id);
self.component_map[storage_id as usize].remove(entity.id as usize);
self.component_map_inv[storage_id as usize].remove(swap as usize);
self.free_map[storage_id].push(entity.id);
self.version[storage_id][entity.id as usize] += Wrapping(1);
}
}
}
pub trait RegisterBorrow {
fn register_borrow() -> Borrow;
}
pub trait PushBorrow {
fn push_borrow(acccess: &mut Borrow) -> bool;
}
impl<T: Component> PushBorrow for Write<T> {
fn push_borrow(borrow: &mut Borrow) -> bool {
borrow.writes.insert(TypeDef::of::<T>())
}
}
impl<T: Component> PushBorrow for Read<T> {
fn push_borrow(borrow: &mut Borrow) -> bool {
borrow.reads.insert(TypeDef::of::<T>());
true
}
}
macro_rules! impl_register_borrow{
($($ty: ident),*) => {
impl<$($ty,)*> RegisterBorrow for ($($ty,)*)
where
$(
$ty: PushBorrow,
)*
{
fn register_borrow() -> Borrow {
let mut borrow = Borrow::new();
let success =
$(
$ty::push_borrow(&mut borrow)
)&&*;
assert!(success, "Detected multiple writes");
borrow
}
}
}
}
impl_register_borrow!(A);
impl_register_borrow!(A, B);
impl_register_borrow!(A, B, C);
impl_register_borrow!(A, B, C, D);
impl_register_borrow!(A, B, C, D, E);
impl_register_borrow!(A, B, C, D, E, F);
impl_register_borrow!(A, B, C, D, E, F, G);
impl_register_borrow!(A, B, C, D, E, F, G, H);
pub struct RuntimeBorrow {
borrows: Vec<Borrow>,
}
impl Default for RuntimeBorrow {
fn default() -> Self {
Self::new()
}
}
impl RuntimeBorrow {
pub fn new() -> Self {
Self {
borrows: Vec::new(),
}
}
pub fn push_access<R: RegisterBorrow>(&mut self) {
let borrow = R::register_borrow();
self.borrows.push(borrow);
}
pub fn pop_access(&mut self) {
self.borrows.pop();
}
pub fn validate(&self) -> Result<(), Vec<TypeDef>> {
let overlapping_borrows: Vec<_> = self
.borrows
.iter()
.enumerate()
.flat_map(|(idx, borrow)| {
let reads = borrow.writes.intersection(&borrow.reads).cloned();
let rest: Vec<_> = self
.borrows
.iter()
.skip(idx + 1)
.flat_map(|next_access| {
let writes = borrow.writes.intersection(&next_access.writes).cloned();
let reads = borrow.writes.intersection(&next_access.reads).cloned();
writes.chain(reads)
})
.collect();
reads.chain(rest)
})
.collect();
if overlapping_borrows.is_empty() {
Ok(())
} else {
Err(overlapping_borrows)
}
}
}
pub struct Borrow {
reads: HashSet<TypeDef>,
writes: HashSet<TypeDef>,
}
impl Default for Borrow {
fn default() -> Self {
Self::new()
}
}
impl Borrow {
pub fn new() -> Self {
Self {
reads: HashSet::new(),
writes: HashSet::new(),
}
}
}
pub trait Component: Send + 'static {}
impl<C: 'static + Send> Component for C {}
pub struct Read<C>(PhantomData<C>);
pub struct Write<C>(PhantomData<C>);
pub trait Fetch<'s> {
type Component: Component;
type Iter: ExactSizeIterator + 's;
unsafe fn fetch<S: Storage>(storage: &'s S) -> Self::Iter;
}
impl<'s, C: Component> Fetch<'s> for Read<C> {
type Component = C;
type Iter = std::slice::Iter<'s, C>;
unsafe fn fetch<S: Storage>(storage: &'s S) -> Self::Iter {
storage.component::<C>().iter()
}
}
impl<'s, C: Component> Fetch<'s> for Write<C> {
type Component = C;
type Iter = std::slice::IterMut<'s, C>;
unsafe fn fetch<S: Storage>(storage: &'s S) -> Self::Iter {
storage.component_mut::<C>().iter_mut()
}
}
pub trait Matcher {
fn is_match<S: Storage>(storage: &S) -> bool;
}
pub trait Query<'s> {
type Borrow;
type Iter: ExactSizeIterator + 's;
unsafe fn query<S: Storage>(storage: &'s S) -> Self::Iter;
}
pub struct All<'s, Tuple>(pub PhantomData<&'s Tuple>);
macro_rules! impl_matcher_all{
($($ty: ident),*) => {
impl<'s, $($ty,)*> Matcher for All<'s, ($($ty,)*)>
where
$(
$ty: Fetch<'s>,
)*
{
fn is_match<S: Storage>(storage: &S) -> bool {
$(
storage.contains::<$ty::Component>()
)&&*
}
}
}
}
impl_matcher_all!(A);
impl_matcher_all!(A, B);
impl_matcher_all!(A, B, C);
impl_matcher_all!(A, B, C, D);
impl_matcher_all!(A, B, C, D, E);
impl_matcher_all!(A, B, C, D, E, F);
impl_matcher_all!(A, B, C, D, E, F, G);
impl_matcher_all!(A, B, C, D, E, F, G, H);
impl<'s, A> Query<'s> for All<'s, A>
where
A: Fetch<'s>,
{
type Borrow = A;
type Iter = A::Iter;
unsafe fn query<S: Storage>(storage: &'s S) -> Self::Iter {
A::fetch(storage)
}
}
macro_rules! impl_query_all{
($($ty: ident),*) => {
impl<'s, $($ty,)*> Query<'s> for All<'s, ($($ty,)*)>
where
$(
$ty: Fetch<'s>,
)*
{
type Borrow = ($($ty,)*);
type Iter = Zip<($($ty::Iter,)*)>;
unsafe fn query<S1: Storage>(storage: &'s S1) -> Self::Iter {
multizip(($($ty::fetch(storage),)*))
}
}
}
}
impl_query_all!(A);
impl_query_all!(A, B);
impl_query_all!(A, B, C);
impl_query_all!(A, B, C, D);
impl_query_all!(A, B, C, D, E);
impl_query_all!(A, B, C, D, E, F);
impl_query_all!(A, B, C, D, E, F, G);
impl_query_all!(A, B, C, D, E, F, G, H);
pub struct EmptyStorage<S> {
storage: S,
}
pub trait BuildStorage {
fn build<S: Storage + RegisterComponent>(id: StorageId) -> EmptyStorage<S>;
}
macro_rules! impl_build_storage {
($($ty: ident),*) => {
impl<$($ty),*> BuildStorage for ($($ty,)*)
where
$(
$ty:Component,
)*
{
fn build<S: Storage + RegisterComponent>(id: StorageId) -> EmptyStorage<S> {
let mut empty = S::empty(id);
$(
empty.register_component::<$ty>();
)*
empty
}
}
}
}
impl_build_storage!(A);
impl_build_storage!(A, B);
impl_build_storage!(A, B, C);
impl_build_storage!(A, B, C, D);
impl_build_storage!(A, B, C, D, E);
impl_build_storage!(A, B, C, D, E, F);
impl_build_storage!(A, B, C, D, E, F, G);
impl_build_storage!(A, B, C, D, E, F, G, H);
impl<S> EmptyStorage<S>
where
S: Storage + RegisterComponent,
{
pub fn register_component<C: Component>(&mut self) {
self.storage.register_component::<C>();
}
pub fn access(self) -> S {
self.storage
}
}
pub trait RuntimeStorage: Downcast {
fn remove(&mut self, id: ComponentId);
}
impl_downcast!(RuntimeStorage);
impl RuntimeStorage {
pub fn as_unsafe_storage<C: Component>(&self) -> &UnsafeStorage<C> {
self.downcast_ref::<UnsafeStorage<C>>()
.expect("Incorrect storage type")
}
pub fn as_unsafe_storage_mut<C: Component>(&mut self) -> &mut UnsafeStorage<C> {
self.downcast_mut::<UnsafeStorage<C>>()
.expect("Incorrect storage type")
}
}
impl<T: Component> RuntimeStorage for UnsafeStorage<T> {
fn remove(&mut self, id: ComponentId) {
unsafe {
self.inner_mut().swap_remove(id as usize);
}
}
}
pub struct UnsafeStorage<T>(UnsafeCell<Vec<T>>);
impl<T> UnsafeStorage<T> {
pub fn new() -> Self {
UnsafeStorage(UnsafeCell::new(Vec::<T>::new()))
}
pub unsafe fn inner_mut(&self) -> &mut Vec<T> {
&mut (*self.0.get())
}
}
pub trait IteratorSoa: Sized {
type Output;
fn to_soa<I: Iterator<Item = Self>>(iter: I) -> Self::Output;
}
macro_rules! impl_iterator_soa {
( $(($item: ident, $ty: ident )),*) => {
impl<$($ty),*> IteratorSoa for ($($ty,)*)
where
$(
$ty: Component,
)*
{
type Output = ($(Vec<$ty>,)*);
fn to_soa<Iter: Iterator<Item = Self>>(iter: Iter) -> Self::Output {
$(
#[allow(non_snake_case)]
let mut $ty = Vec::new();
)*
for ($($item,)*) in iter {
$(
$ty.push($item);
)*
}
($($ty,)*)
}
}
}
}
impl_iterator_soa!((a, A));
impl_iterator_soa!((a, A), (b, B));
impl_iterator_soa!((a, A), (b, B), (c, C));
impl_iterator_soa!((a, A), (b, B), (c, C), (d, D));
impl_iterator_soa!((a, A), (b, B), (c, C), (d, D), (e, E));
impl_iterator_soa!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F));
impl_iterator_soa!((a, A), (b, B), (c, C), (d, D), (e, E), (f, F), (g, G));
impl_iterator_soa!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H)
);
impl_iterator_soa!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H),
(i, I)
);
impl_iterator_soa!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H),
(i, I),
(j, J)
);
impl_iterator_soa!(
(a, A),
(b, B),
(c, C),
(d, D),
(e, E),
(f, F),
(g, G),
(h, H),
(i, I),
(j, J),
(k, K)
);
pub trait AppendComponents
where
Self: IteratorSoa,
{
fn is_match<S: Storage>(storage: &S) -> bool;
fn append_components<I, S>(items: I, storage: &mut S) -> usize
where
S: Storage,
I: IntoIterator<Item = Self>;
}
macro_rules! impl_append_components {
($size: expr => $($ty: ident),*) => {
impl<$($ty),*> AppendComponents for ($($ty,)*)
where
$(
$ty: Component,
)*
{
fn is_match<S: Storage>(storage: &S) -> bool {
let types = storage.types();
let mut b = types.len() == $size;
$(
b &= types.contains(&TypeId::of::<$ty>());
)*
b
}
fn append_components<Iter, S>(items: Iter, storage: &mut S) -> usize
where
S: Storage,
Iter: IntoIterator<Item = Self>,
{
let tuple = Self::to_soa(items.into_iter());
let len = tuple.0.len();
#[allow(non_snake_case)]
let ($($ty,)*) = tuple;
$(
storage.push_components($ty);
)*
*storage.len_mut() += len;
len
}
}
}
}
impl_append_components!(1 => A);
impl_append_components!(2 => A, B);
impl_append_components!(3 => A, B, C);
impl_append_components!(4 => A, B, C, D);
impl_append_components!(5 => A, B, C, D, E);
impl_append_components!(6 => A, B, C, D, E, F);
impl_append_components!(7 => A, B, C, D, E, F, G);
impl_append_components!(8 => A, B, C, D, E, F, G, H);
impl_append_components!(9 => A, B, C, D, E, F, G, H, I);
impl_append_components!(10 => A, B, C, D, E, F, G, H, I, J);
impl_append_components!(11 => A, B, C, D, E, F, G, H, I, J, K);
pub struct SoaStorage {
len: usize,
id: StorageId,
types: HashSet<TypeId>,
storages: HashMap<TypeId, Box<RuntimeStorage>>,
}
pub trait RegisterComponent {
fn register_component<C: Component>(&mut self);
}
impl RegisterComponent for SoaStorage {
fn register_component<C: Component>(&mut self) {
let type_id = TypeId::of::<C>();
self.types.insert(type_id);
self.storages
.insert(type_id, Box::new(UnsafeStorage::<C>::new()));
}
}
pub trait Storage: Sized {
fn len(&self) -> usize;
fn len_mut(&mut self) -> &mut usize;
fn id(&self) -> StorageId;
fn empty(id: StorageId) -> EmptyStorage<Self>;
unsafe fn component<C: Component>(&self) -> &[C];
unsafe fn component_mut<C: Component>(&self) -> &mut [C];
fn push_components<C, I>(&mut self, components: I)
where
C: Component,
I: IntoIterator<Item = C>;
fn push_component<C: Component>(&mut self, component: C);
fn contains<C: Component>(&self) -> bool;
fn types(&self) -> &HashSet<TypeId>;
fn remove(&mut self, id: ComponentId) -> usize;
}
impl SoaStorage {
fn get_storage<C: Component>(&self) -> &UnsafeStorage<C> {
let runtime_storage = self
.storages
.get(&TypeId::of::<C>())
.expect("Unknown storage");
runtime_storage.as_unsafe_storage::<C>()
}
fn get_storage_mut<C: Component>(&mut self) -> &mut UnsafeStorage<C> {
let runtime_storage = self
.storages
.get_mut(&TypeId::of::<C>())
.expect("Unknown storage");
runtime_storage.as_unsafe_storage_mut::<C>()
}
}
impl Storage for SoaStorage {
fn len(&self) -> usize {
self.len
}
fn len_mut(&mut self) -> &mut usize {
&mut self.len
}
fn remove(&mut self, id: ComponentId) -> usize {
self.storages.values_mut().for_each(|storage| {
storage.remove(id);
});
self.len -= 1;
self.len
}
fn id(&self) -> StorageId {
self.id
}
fn push_components<C, I>(&mut self, components: I)
where
C: Component,
I: IntoIterator<Item = C>,
{
unsafe {
self.get_storage_mut::<C>().inner_mut().extend(components);
}
}
fn push_component<C: Component>(&mut self, component: C) {
unsafe {
self.get_storage::<C>().inner_mut().push(component);
}
}
fn empty(id: StorageId) -> EmptyStorage<Self> {
let storage = SoaStorage {
types: HashSet::new(),
storages: HashMap::new(),
id,
len: 0,
};
EmptyStorage { storage }
}
unsafe fn component_mut<C: Component>(&self) -> &mut [C] {
self.get_storage::<C>().inner_mut().as_mut_slice()
}
unsafe fn component<C: Component>(&self) -> &[C] {
self.get_storage::<C>().inner_mut().as_slice()
}
fn contains<C: Component>(&self) -> bool {
self.types.contains(&TypeId::of::<C>())
}
fn types(&self) -> &HashSet<TypeId> {
&self.types
}
}