summaryrefslogtreecommitdiff
path: root/ecs/src
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src')
-rw-r--r--ecs/src/component.rs6
-rw-r--r--ecs/src/component/storage.rs37
-rw-r--r--ecs/src/lib.rs4
-rw-r--r--ecs/src/query.rs17
-rw-r--r--ecs/src/system.rs15
-rw-r--r--ecs/src/system/stateful.rs12
6 files changed, 48 insertions, 43 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 512c60d..be5756f 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -121,6 +121,7 @@ pub struct Id
impl Id
{
+ #[must_use]
pub fn of<ComponentT>() -> Self
where
ComponentT: Component,
@@ -168,6 +169,7 @@ impl From<bool> for IsOptional
/// Returns whether the given component type is a optional component.
///
/// Will return `true` if the component is a [`Option`].
+#[must_use]
pub fn is_optional<ComponentT: Component>() -> bool
{
if Id::of::<ComponentT>() == Id::of::<Option<ComponentT::Component>>() {
@@ -177,7 +179,7 @@ pub fn is_optional<ComponentT: Component>() -> bool
false
}
-pub trait FromOptionalComponent<'comp>
+pub trait FromOptional<'comp>
{
fn from_optional_component(
optional_component: Option<WriteGuard<'comp, Box<dyn Component>>>,
@@ -189,7 +191,7 @@ macro_rules! inner {
seq!(I in 0..=$c {
impl<#(Comp~I: Component,)*> Sequence for (#(Comp~I,)*)
where
- #(for<'comp> Comp~I::RefMut<'comp>: FromOptionalComponent<'comp>,)*
+ #(for<'comp> Comp~I::RefMut<'comp>: FromOptional<'comp>,)*
{
type Refs<'component> = (#(Comp~I::RefMut<'component>,)*)
where Self: 'component;
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 86f28fc..42e0e4f 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -9,7 +9,7 @@ use crate::type_name::TypeName;
use crate::EntityComponent;
#[derive(Debug, Default)]
-pub struct ComponentStorage
+pub struct Storage
{
archetypes: Vec<Archetype>,
archetype_lookup: HashMap<ArchetypeComponentsHash, Vec<usize>>,
@@ -20,7 +20,15 @@ pub struct ComponentStorage
pub struct ArchetypeRefIter<'component_storage>
{
inner: SliceIter<'component_storage, usize>,
- archetypes: &'component_storage Vec<Archetype>,
+ archetypes: &'component_storage [Archetype],
+}
+
+impl<'component_storage> ArchetypeRefIter<'component_storage>
+{
+ fn new_empty() -> Self
+ {
+ Self { inner: [].iter(), archetypes: &[] }
+ }
}
impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
@@ -39,12 +47,12 @@ impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage>
}
}
-impl ComponentStorage
+impl Storage
{
pub fn find_entities(
&self,
component_ids: &[(ComponentId, ComponentIsOptional)],
- ) -> Option<ArchetypeRefIter<'_>>
+ ) -> ArchetypeRefIter<'_>
{
let ids = component_ids
.iter()
@@ -58,9 +66,11 @@ impl ComponentStorage
self.archetype_lookup
.get(&ArchetypeComponentsHash::new(ids))
- .map(|archetypes_indices| ArchetypeRefIter {
- inner: archetypes_indices.iter(),
- archetypes: &self.archetypes,
+ .map_or_else(ArchetypeRefIter::new_empty, |archetypes_indices| {
+ ArchetypeRefIter {
+ inner: archetypes_indices.iter(),
+ archetypes: &self.archetypes,
+ }
})
}
@@ -136,10 +146,7 @@ impl ComponentStorage
self.archetype_lookup.clear();
for pending_entry in self.pending_archetype_lookup_entries.drain(..) {
- let components_set: HashSet<_> = pending_entry
- .iter()
- .map(|component_id| *component_id)
- .collect();
+ let components_set: HashSet<_> = pending_entry.iter().copied().collect();
let matching_archetype_indices = self
.archetypes
@@ -163,7 +170,7 @@ impl ComponentStorage
}
}
-impl TypeName for ComponentStorage
+impl TypeName for Storage
{
fn type_name(&self) -> &'static str
{
@@ -207,7 +214,7 @@ mod tests
use ecs_macros::Component;
- use super::{Archetype, ArchetypeComponentsHash, ComponentStorage};
+ use super::{Archetype, ArchetypeComponentsHash, Storage};
use crate::component::Id as ComponentId;
use crate::lock::Lock;
use crate::{self as ecs, EntityComponent};
@@ -242,7 +249,7 @@ mod tests
#[test]
fn push_entity_works()
{
- let mut component_storage = ComponentStorage::default();
+ let mut component_storage = Storage::default();
component_storage.push_entity(vec![
Box::new(HealthPotion { _hp_restoration: 12 }),
@@ -288,7 +295,7 @@ mod tests
#[test]
fn lookup_works()
{
- let mut component_storage = ComponentStorage::default();
+ let mut component_storage = Storage::default();
component_storage.archetypes.push(Archetype {
component_ids: HashSet::from([
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 42cdef3..b883171 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -10,7 +10,7 @@ use std::sync::Arc;
use std::vec::Drain;
use crate::actions::Action;
-use crate::component::storage::ComponentStorage;
+use crate::component::storage::Storage as ComponentStorage;
use crate::component::{Component, Id as ComponentId, Sequence as ComponentSequence};
use crate::event::{Event, Id as EventId, Ids, Sequence as EventSequence};
use crate::extension::{Collector as ExtensionCollector, Extension};
@@ -62,7 +62,7 @@ impl World
.component_storage
.write_nonblock()
.expect("Failed to acquire read-write component storage lock")
- .push_entity(components.into_vec())
+ .push_entity(components.into_vec());
}
/// Adds a globally shared singleton value.
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index dcd0b0e..dc6b5f0 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -1,10 +1,14 @@
-use std::any::{type_name, Any};
+use std::any::Any;
use std::collections::HashSet;
use std::iter::{Flatten, Map};
use std::marker::PhantomData;
use std::sync::{Arc, Weak};
-use crate::component::storage::{Archetype, ArchetypeRefIter};
+use crate::component::storage::{
+ Archetype,
+ ArchetypeRefIter,
+ Storage as ComponentStorage,
+};
use crate::component::{
Id as ComponentId,
IsOptional as ComponentIsOptional,
@@ -16,7 +20,7 @@ use crate::system::{
Param as SystemParam,
System,
};
-use crate::{ComponentStorage, EntityComponent, WorldData};
+use crate::{EntityComponent, WorldData};
#[derive(Debug)]
pub struct Query<'world, Comps>
@@ -32,19 +36,20 @@ impl<'world, Comps> Query<'world, Comps>
where
Comps: ComponentSequence,
{
+ /// Iterates over the entities matching this query.
#[must_use]
pub fn iter<'this>(&'this self) -> ComponentIter<'world, Comps>
where
'this: 'world,
{
#[cfg(feature = "debug")]
- tracing::debug!("Searching for {}", type_name::<Comps>());
+ tracing::debug!("Searching for {}", std::any::type_name::<Comps>());
+ #[allow(clippy::map_flatten)]
ComponentIter {
entities: self
.component_storage
.find_entities(&Comps::ids())
- .unwrap_or_else(|| panic!("Could not find {:?}", type_name::<Comps>()))
.map((|archetype| archetype.components.as_slice()) as ComponentIterMapFn)
.flatten(),
comps_pd: PhantomData,
@@ -136,7 +141,7 @@ where
#[cfg(feature = "debug")]
tracing::debug!(
"Adding archetypes lookup entry for components: ({})",
- type_name::<Comps>()
+ std::any::type_name::<Comps>()
);
component_storage_lock.add_archetype_lookup_entry(
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
index f8885fc..57b0756 100644
--- a/ecs/src/system.rs
+++ b/ecs/src/system.rs
@@ -4,11 +4,10 @@ use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::panic::{RefUnwindSafe, UnwindSafe};
-use std::ptr::addr_of;
use seq_macro::seq;
-use crate::component::{Component, FromOptionalComponent};
+use crate::component::{Component, FromOptional as FromOptionalComponent};
use crate::lock::WriteGuard;
use crate::system::util::check_params_are_compatible;
use crate::tuple::{ReduceElement as TupleReduceElement, With as TupleWith};
@@ -88,7 +87,7 @@ macro_rules! impl_system {
run: Box::new(|data, world_data| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let data = unsafe { &*addr_of!(*data) };
+ let data = unsafe { &*std::ptr::from_ref(data) };
let me = data
.downcast_ref::<Func>()
@@ -96,16 +95,14 @@ macro_rules! impl_system {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let world_data = unsafe {
- &*(world_data as *const WorldData)
- };
+ let world_data = unsafe { &*std::ptr::from_ref(world_data) };
me.run(world_data);
}),
prepare: Box::new(|data, world_data| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let data = unsafe { &*addr_of!(*data) };
+ let data = unsafe { &*std::ptr::from_ref(data) };
let me = data
.downcast_ref::<Func>()
@@ -113,9 +110,7 @@ macro_rules! impl_system {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let world_data = unsafe {
- &*(world_data as *const WorldData)
- };
+ let world_data = unsafe { &*std::ptr::from_ref(world_data) };
me.prepare(world_data);
}),
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs
index 49fd3bf..56c9d4f 100644
--- a/ecs/src/system/stateful.rs
+++ b/ecs/src/system/stateful.rs
@@ -114,30 +114,26 @@ macro_rules! impl_system {
run: Box::new(|data, world_data| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let data = unsafe { &*(data as *const dyn Any) };
+ let data = unsafe { &*std::ptr::from_ref::<dyn Any>(data) };
let me = data.downcast_ref::<Self>().unwrap();
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let world_data = unsafe {
- &*(world_data as *const WorldData)
- };
+ let world_data = unsafe { &*std::ptr::from_ref(world_data) };
me.run(world_data);
}),
prepare: Box::new(|data, world_data| {
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let data = unsafe { &*(data as *const dyn Any) };
+ let data = unsafe { &*std::ptr::from_ref::<dyn Any>(data) };
let me = data.downcast_ref::<Self>().unwrap();
// SAFETY: The caller of TypeErased::run ensures the lifetime
// is correct
- let world_data = unsafe {
- &*(world_data as *const WorldData)
- };
+ let world_data = unsafe { &*std::ptr::from_ref(world_data) };
me.prepare(world_data);
}),