diff options
Diffstat (limited to 'ecs/src')
-rw-r--r-- | ecs/src/component.rs | 6 | ||||
-rw-r--r-- | ecs/src/component/storage.rs | 37 | ||||
-rw-r--r-- | ecs/src/lib.rs | 4 | ||||
-rw-r--r-- | ecs/src/query.rs | 17 | ||||
-rw-r--r-- | ecs/src/system.rs | 15 | ||||
-rw-r--r-- | ecs/src/system/stateful.rs | 12 |
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); }), |