diff options
Diffstat (limited to 'ecs/src')
| -rw-r--r-- | ecs/src/actions.rs | 8 | ||||
| -rw-r--r-- | ecs/src/component.rs | 8 | ||||
| -rw-r--r-- | ecs/src/component/storage.rs | 53 | ||||
| -rw-r--r-- | ecs/src/component/storage/archetype.rs | 23 | ||||
| -rw-r--r-- | ecs/src/entity.rs | 20 | ||||
| -rw-r--r-- | ecs/src/lib.rs | 169 | ||||
| -rw-r--r-- | ecs/src/pair.rs | 29 | ||||
| -rw-r--r-- | ecs/src/query.rs | 11 | ||||
| -rw-r--r-- | ecs/src/query/flexible.rs | 31 | ||||
| -rw-r--r-- | ecs/src/uid.rs | 13 | ||||
| -rw-r--r-- | ecs/src/util.rs | 2 | ||||
| -rw-r--r-- | ecs/src/util/array_vec.rs | 24 | 
12 files changed, 185 insertions, 206 deletions
| diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs index f366b4c..e0efeda 100644 --- a/ecs/src/actions.rs +++ b/ecs/src/actions.rs @@ -1,5 +1,5 @@  use std::marker::PhantomData; -use std::sync::{Arc, Weak}; +use std::rc::{Rc, Weak};  use crate::component::{Parts as ComponentParts, Sequence as ComponentSequence};  use crate::system::{Param as SystemParam, System}; @@ -87,11 +87,11 @@ impl<'world> Actions<'world>          }      } -    fn new(action_queue: &'world Arc<ActionQueue>) -> Self +    fn new(action_queue: &'world Rc<ActionQueue>) -> Self      {          Self {              action_queue, -            action_queue_weak: Arc::downgrade(action_queue), +            action_queue_weak: Rc::downgrade(action_queue),          }      }  } @@ -142,7 +142,7 @@ impl WeakRef  #[derive(Debug, Clone)]  pub struct Ref<'weak_ref>  { -    action_queue: Arc<ActionQueue>, +    action_queue: Rc<ActionQueue>,      _pd: PhantomData<&'weak_ref ()>,  } diff --git a/ecs/src/component.rs b/ecs/src/component.rs index de4384b..a0ed752 100644 --- a/ecs/src/component.rs +++ b/ecs/src/component.rs @@ -99,6 +99,9 @@ pub trait HandleFromEntityComponentRef<'comp>: Sized      type Error: Error;      /// Creates a new handle instance from a [`EntityComponentRef`]. +    /// +    /// # Errors +    /// See the implementation's [`Self::Error`] type.      fn from_entity_component_ref(          entity_component_ref: Option<EntityComponentRef<'comp>>,          world: &'comp World, @@ -306,16 +309,19 @@ pub struct Parts  impl Parts  { +    #[must_use]      pub fn id(&self) -> Uid      {          self.id      } +    #[must_use]      pub fn name(&self) -> &'static str      {          self.name      } +    #[must_use]      pub fn builder() -> PartsBuilder      {          PartsBuilder::default() @@ -335,12 +341,14 @@ pub struct PartsBuilder  impl PartsBuilder  { +    #[must_use]      pub fn name(mut self, name: &'static str) -> Self      {          self.name = name;          self      } +    #[must_use]      pub fn build<Data: 'static>(self, id: Uid, data: Data) -> Parts      {          Parts { diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs index 14f3ea4..f5cce57 100644 --- a/ecs/src/component/storage.rs +++ b/ecs/src/component/storage.rs @@ -216,38 +216,35 @@ impl Storage              });          } -        let add_edge_archetype_id = match archetype_node +        let add_edge_archetype_id = if let Some(add_edge_id) = archetype_node              .get_or_insert_edges(component_id, ArchetypeEdges::default)              .add          { -            Some(add_edge_id) => { -                if !self.graph.contains_archetype(add_edge_id) { -                    let (_, add_edge_comp_ids) = self -                        .graph -                        .get_node_by_id(archetype_id) -                        .expect("Archetype should exist") -                        .make_add_edge(component_id); - -                    self.graph.create_node(add_edge_id, &add_edge_comp_ids); -                } - -                add_edge_id -            } -            None => { -                let archetype_node = self +            if !self.graph.contains_archetype(add_edge_id) { +                let (_, add_edge_comp_ids) = self                      .graph                      .get_node_by_id(archetype_id) -                    .expect("Archetype should exist"); +                    .expect("Archetype should exist") +                    .make_add_edge(component_id); -                let (add_edge_id, add_edge_comp_ids) = -                    archetype_node.make_add_edge(component_id); +                self.graph.create_node(add_edge_id, &add_edge_comp_ids); +            } -                if !self.graph.contains_archetype(add_edge_id) { -                    self.graph.create_node(add_edge_id, &add_edge_comp_ids); -                } +            add_edge_id +        } else { +            let archetype_node = self +                .graph +                .get_node_by_id(archetype_id) +                .expect("Archetype should exist"); -                add_edge_id +            let (add_edge_id, add_edge_comp_ids) = +                archetype_node.make_add_edge(component_id); + +            if !self.graph.contains_archetype(add_edge_id) { +                self.graph.create_node(add_edge_id, &add_edge_comp_ids);              } + +            add_edge_id          };          let archetype_node = self @@ -592,8 +589,7 @@ pub struct ArchetypeRefIter<'storage, 'search_terms>      search_terms: ArchetypeSearchTerms<'search_terms>,  } -impl<'component_storage, 'search_terms> Iterator -    for ArchetypeRefIter<'component_storage, 'search_terms> +impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage, '_>  {      type Item = &'component_storage Archetype; @@ -646,10 +642,7 @@ impl<'component_storage, 'search_terms> Iterator                      self.storage.imaginary_archetypes.borrow_mut().push(                          ImaginaryArchetype {                              id: add_edge_archetype_id, -                            component_ids: add_edge_archetype_comps -                                .iter() -                                .map(|comp_id| *comp_id) -                                .collect::<Vec<_>>(), +                            component_ids: add_edge_archetype_comps.clone(),                          },                      ); @@ -663,8 +656,6 @@ impl<'component_storage, 'search_terms> Iterator                          )),                          found.into_iter(),                      )); - -                    continue;                  }                  _ => {                      unreachable!(); diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs index f8c204b..56dd5ae 100644 --- a/ecs/src/component/storage/archetype.rs +++ b/ecs/src/component/storage/archetype.rs @@ -155,7 +155,7 @@ impl Archetype              inner: Either::B(                  [component_id]                      .into_iter() -                    .zip(self.get_index_for_component(component_id).into_iter()), +                    .zip(self.get_index_for_component(component_id)),              ),          }      } @@ -219,19 +219,20 @@ type MatchingComponentIterFilterFn = fn(&((usize, &Uid), Uid)) -> bool;  type MatchingComponentIterMapFn = fn(((usize, &Uid), Uid)) -> (Uid, usize); +type InnerMatchingComponentIterA<'archetype> = Map< +    Filter< +        Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>, +        MatchingComponentIterFilterFn, +    >, +    MatchingComponentIterMapFn, +>; + +type InnerMatchingComponentIterB = Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>; +  #[derive(Debug)]  pub struct MatchingComponentIter<'archetype>  { -    inner: Either< -        Map< -            Filter< -                Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>, -                MatchingComponentIterFilterFn, -            >, -            MatchingComponentIterMapFn, -        >, -        Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>, -    >, +    inner: Either<InnerMatchingComponentIterA<'archetype>, InnerMatchingComponentIterB>,  }  impl Iterator for MatchingComponentIter<'_> diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs index 3f5a3d3..562f7ea 100644 --- a/ecs/src/entity.rs +++ b/ecs/src/entity.rs @@ -35,6 +35,14 @@ impl<'a> Handle<'a>          self.entity.uid()      } +    /// Returns a reference to the specified component in this entity. `None` is +    /// returned if the component isn't found in the entity. +    /// +    /// # Panics +    /// Will panic if: +    /// - The component's ID is not a component ID +    /// - The component is mutably borrowed elsewhere +    #[must_use]      pub fn get<ComponentT: Component>(&self) -> Option<ComponentHandle<'_, ComponentT>>      {          assert_eq!(ComponentT::id().kind(), UidKind::Component); @@ -52,6 +60,14 @@ impl<'a> Handle<'a>          )      } +    /// Returns a mutable reference to the specified component in this entity. `None` is +    /// returned if the component isn't found in the entity. +    /// +    /// # Panics +    /// Will panic if: +    /// - The component's ID is not a component ID +    /// - The component is borrowed elsewhere +    #[must_use]      pub fn get_mut<ComponentT: Component>(          &self,      ) -> Option<ComponentHandleMut<'_, ComponentT>> @@ -131,7 +147,7 @@ macro_rules! static_entity {                      $crate::entity::CREATE_STATIC_ENTITIES                  )]                  #[linkme(crate=$crate::private::linkme)] -                static CREATE_STATIC_ENTITY: fn(&$crate::World) = |world| { +                static CREATE_STATIC_ENTITY: fn(&mut $crate::World) = |world| {                      world.create_entity_with_uid($components, *$ident);                  };              } @@ -141,4 +157,4 @@ macro_rules! static_entity {  #[distributed_slice]  #[doc(hidden)] -pub static CREATE_STATIC_ENTITIES: [fn(&World)]; +pub static CREATE_STATIC_ENTITIES: [fn(&mut World)]; diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index dd43e0b..c953290 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -4,6 +4,7 @@ use std::any::{type_name, Any, TypeId};  use std::cell::RefCell;  use std::fmt::Debug;  use std::mem::ManuallyDrop; +use std::rc::Rc;  use std::sync::atomic::{AtomicBool, Ordering};  use std::sync::Arc; @@ -23,7 +24,7 @@ use crate::event::component::{      Removed as ComponentRemovedEvent,  };  use crate::extension::{Collector as ExtensionCollector, Extension}; -use crate::lock::{Lock, WriteGuard}; +use crate::lock::Lock;  use crate::pair::{ChildOf, DependsOn, Pair};  use crate::phase::{Phase, START as START_PHASE};  use crate::query::flexible::Query as FlexibleQuery; @@ -86,7 +87,7 @@ impl World          world.add_sole(Stats::default()).ok();          for create_static_entity in CREATE_STATIC_ENTITIES { -            create_static_entity(&world); +            create_static_entity(&mut world);          }          world @@ -109,29 +110,23 @@ impl World      #[tracing::instrument(skip_all)]      #[doc(hidden)] -    pub fn create_entity_with_uid<Comps>(&self, components: Comps, entity_uid: Uid) +    pub fn create_entity_with_uid<Comps>(&mut self, components: Comps, entity_uid: Uid)      where          Comps: ComponentSequence,      {          debug_assert_eq!(entity_uid.kind(), UidKind::Entity); -        let added_component_ids; - -        { -            let mut component_storage_lock = self.lock_component_storage_rw(); - -            if let Err(err) = component_storage_lock.create_entity(entity_uid) { -                tracing::warn!("Failed to create entity: {err}"); -                return; -            }; - -            added_component_ids = Self::add_entity_components( -                entity_uid, -                components.into_parts_array(), -                &mut component_storage_lock, -            ); +        if let Err(err) = self.data.component_storage.create_entity(entity_uid) { +            tracing::warn!("Failed to create entity: {err}"); +            return;          } +        let added_component_ids = Self::add_entity_components( +            entity_uid, +            components.into_parts_array(), +            &mut self.data.component_storage, +        ); +          for comp_id in added_component_ids {              self.emit_event_by_id::<ComponentAddedEvent>(comp_id);          } @@ -203,7 +198,7 @@ impl World      ///      /// # Panics      /// Will panic if a internal lock cannot be acquired. -    pub fn step(&self) -> StepResult +    pub fn step(&mut self) -> StepResult      {          if self.stop.load(Ordering::Relaxed) {              return StepResult::Stop; @@ -219,8 +214,7 @@ impl World          self.perform_phases(); -        self.lock_component_storage_rw() -            .create_imaginary_archetypes(); +        self.data.component_storage.create_imaginary_archetypes();          self.perform_queued_actions(); @@ -249,7 +243,7 @@ impl World      ///      /// # Panics      /// Will panic if a internal lock cannot be acquired. -    pub fn start_loop(&self) +    pub fn start_loop(&mut self)      {          while let StepResult::Continue = self.step() {}      } @@ -267,13 +261,7 @@ impl World              VizoxideArchetypeGraphParams,          }; -        let component_storage_lock = self -            .data -            .component_storage -            .read_nonblock() -            .expect("Failed to acquire read-only component storage lock"); - -        component_storage_lock.create_vizoxide_archetype_graph( +        self.data.component_storage.create_vizoxide_archetype_graph(              name,              VizoxideArchetypeGraphParams {                  create_node_name: |archetype, _| { @@ -339,7 +327,7 @@ impl World                  .build(),          ); -        for child_phase_entity in phase_query.iter() { +        for child_phase_entity in &phase_query {              self.query_and_run_systems(child_phase_entity.uid());              self.perform_child_phases(child_phase_entity.uid());          } @@ -360,7 +348,7 @@ impl World      }      #[tracing::instrument(skip_all)] -    fn perform_queued_actions(&self) +    fn perform_queued_actions(&mut self)      {          let mut active_action_queue = match *self.data.action_queue.active_queue.borrow()          { @@ -380,27 +368,21 @@ impl World          for action in active_action_queue.drain(..) {              match action {                  Action::Spawn(components) => { -                    let added_component_ids; +                    let new_entity_uid = Uid::new_unique(UidKind::Entity); +                    if let Err(err) = +                        self.data.component_storage.create_entity(new_entity_uid)                      { -                        let mut component_storage_lock = self.lock_component_storage_rw(); - -                        let new_entity_uid = Uid::new_unique(UidKind::Entity); - -                        if let Err(err) = -                            component_storage_lock.create_entity(new_entity_uid) -                        { -                            tracing::warn!("Failed to create entity: {err}"); -                            continue; -                        }; - -                        added_component_ids = Self::add_entity_components( -                            new_entity_uid, -                            components, -                            &mut component_storage_lock, -                        ); +                        tracing::warn!("Failed to create entity: {err}"); +                        continue;                      } +                    let added_component_ids = Self::add_entity_components( +                        new_entity_uid, +                        components, +                        &mut self.data.component_storage, +                    ); +                      if !has_swapped_active_queue {                          self.swap_event_queue(&mut has_swapped_active_queue);                      } @@ -410,20 +392,31 @@ impl World                      }                  }                  Action::Despawn(entity_uid) => { -                    self.despawn_entity(entity_uid, &mut has_swapped_active_queue); -                } -                Action::AddComponents(entity_uid, components) => { -                    let added_component_ids; +                    let removed_entity = +                        match self.data.component_storage.remove_entity(entity_uid) { +                            Ok(components) => components, +                            Err(err) => { +                                tracing::error!("Failed to despawn entity: {err}"); +                                return; +                            } +                        }; -                    { -                        let mut component_storage_lock = self.lock_component_storage_rw(); +                    if !has_swapped_active_queue { +                        self.swap_event_queue(&mut has_swapped_active_queue); +                    } -                        added_component_ids = Self::add_entity_components( -                            entity_uid, -                            components, -                            &mut component_storage_lock, +                    for removed_ent_comp in removed_entity.components() { +                        self.emit_event_by_id::<ComponentRemovedEvent>( +                            removed_ent_comp.id(),                          );                      } +                } +                Action::AddComponents(entity_uid, components) => { +                    let added_component_ids = Self::add_entity_components( +                        entity_uid, +                        components, +                        &mut self.data.component_storage, +                    );                      if !has_swapped_active_queue {                          self.swap_event_queue(&mut has_swapped_active_queue); @@ -434,17 +427,11 @@ impl World                      }                  }                  Action::RemoveComponents(entity_uid, component_ids) => { -                    let removed_component_ids; - -                    { -                        let mut component_storage_lock = self.lock_component_storage_rw(); - -                        removed_component_ids = Self::remove_entity_components( -                            entity_uid, -                            component_ids, -                            &mut component_storage_lock, -                        ); -                    } +                    let removed_component_ids = Self::remove_entity_components( +                        entity_uid, +                        component_ids, +                        &mut self.data.component_storage, +                    );                      if !has_swapped_active_queue {                          self.swap_event_queue(&mut has_swapped_active_queue); @@ -461,30 +448,6 @@ impl World          }      } -    #[tracing::instrument(skip_all)] -    fn despawn_entity(&self, entity_uid: Uid, has_swapped_active_queue: &mut bool) -    { -        let mut component_storage_lock = self.lock_component_storage_rw(); - -        let removed_entity = match component_storage_lock.remove_entity(entity_uid) { -            Ok(components) => components, -            Err(err) => { -                tracing::error!("Failed to despawn entity: {err}"); -                return; -            } -        }; - -        drop(component_storage_lock); - -        if !*has_swapped_active_queue { -            self.swap_event_queue(has_swapped_active_queue); -        } - -        for removed_ent_comp in removed_entity.components() { -            self.emit_event_by_id::<ComponentRemovedEvent>(removed_ent_comp.id()); -        } -    } -      fn add_entity_components(          entity_uid: Uid,          components: impl IntoIterator<Item = ComponentParts>, @@ -568,14 +531,6 @@ impl World          *has_swapped_active_queue = true;      } - -    fn lock_component_storage_rw(&self) -> WriteGuard<'_, ComponentStorage> -    { -        self.data -            .component_storage -            .write_nonblock() -            .expect("Failed to acquire read-write component storage lock") -    }  }  impl Default for World @@ -599,9 +554,9 @@ pub enum StepResult  #[derive(Debug)]  pub struct WorldData  { -    component_storage: Arc<Lock<ComponentStorage>>, +    component_storage: ComponentStorage,      sole_storage: SoleStorage, -    action_queue: Arc<ActionQueue>, +    action_queue: Rc<ActionQueue>,  }  impl Default for WorldData @@ -609,12 +564,9 @@ impl Default for WorldData      fn default() -> Self      {          Self { -            component_storage: Arc::new(Lock::new( -                ComponentStorage::default(), -                type_name::<ComponentStorage>(), -            )), +            component_storage: ComponentStorage::default(),              sole_storage: SoleStorage::default(), -            action_queue: Arc::new(ActionQueue::default()), +            action_queue: Rc::new(ActionQueue::default()),          }      }  } @@ -633,6 +585,7 @@ impl<'a> EntityComponentRef<'a>          self.component.component()      } +    #[must_use]      pub fn id(&self) -> Uid      {          self.component_id diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs index 27e535e..2055d5e 100644 --- a/ecs/src/pair.rs +++ b/ecs/src/pair.rs @@ -1,12 +1,10 @@  use std::convert::Infallible; -use crate::component::storage::Storage as ComponentStorage;  use crate::component::{IntoParts as IntoComponentParts, Parts as ComponentParts};  use crate::entity::{      Handle as EntityHandle,      MatchingComponentIter as EntityMatchingComponentIter,  }; -use crate::lock::ReadGuard;  use crate::query::{      TermWithField as QueryTermWithField,      TermsBuilder as QueryTermsBuilder, @@ -24,14 +22,16 @@ pub struct Pair<RelationElem: Element, TargetElem: Element>  impl Pair<Uid, Uid>  { +    #[must_use]      pub fn new<Relation: WithUid>(target: Uid) -> Self      {          Self { relation: Relation::uid(), target }      } +    #[must_use]      pub fn id(&self) -> Uid      { -        Uid::new_pair(UidPairParams { +        Uid::new_pair(&UidPairParams {              relation: self.relation,              target: self.target,          }) @@ -72,7 +72,6 @@ where          Handle {              world, -            component_storage_lock: world.data.component_storage.read_nonblock().unwrap(),              pair_uid: first_matching_comp.id(),          }      } @@ -85,7 +84,7 @@ where  {      fn uid() -> Uid      { -        Uid::new_pair(UidPairParams { +        Uid::new_pair(&UidPairParams {              relation: Relation::uid(),              target: Target::uid(),          }) @@ -121,21 +120,25 @@ where  pub struct Handle<'world>  {      world: &'world World, -    component_storage_lock: ReadGuard<'world, ComponentStorage>,      pair_uid: Uid,  }  impl Handle<'_>  { +    #[must_use]      pub fn get_target_entity(&self) -> Option<EntityHandle<'_>>      {          let archetype = self -            .component_storage_lock +            .world +            .data +            .component_storage              .get_entity_archetype(self.pair_uid.target_entity())?; -        let archetype_entity = archetype -            .get_entity_by_id(self.pair_uid.target_entity()) -            .expect("Not possible"); +        let Some(archetype_entity) = +            archetype.get_entity_by_id(self.pair_uid.target_entity()) +        else { +            unreachable!(); +        };          Some(EntityHandle::new(self.world, archetype, archetype_entity))      } @@ -157,12 +160,6 @@ impl<'a> Iterator for HandleIter<'a>          Some(Handle {              world: self.world, -            component_storage_lock: self -                .world -                .data -                .component_storage -                .read_nonblock() -                .unwrap(),              pair_uid: matching_comp.id(),          })      } diff --git a/ecs/src/query.rs b/ecs/src/query.rs index 1947c18..7e10c5b 100644 --- a/ecs/src/query.rs +++ b/ecs/src/query.rs @@ -168,12 +168,14 @@ impl<const MAX_TERM_CNT: usize> Terms<MAX_TERM_CNT>  }  #[derive(Debug, Default)] +#[must_use]  pub struct TermsBuilder<const MAX_TERM_CNT: usize>  {      required_components: ArrayVec<Uid, MAX_TERM_CNT>,      excluded_components: ArrayVec<Uid, MAX_TERM_CNT>,  } +#[allow(clippy::return_self_not_must_use)]  pub trait TermsBuilderInterface  {      fn with<WithUidT: WithUid>(self) -> Self; @@ -233,7 +235,7 @@ impl_terms_builder! {              ids.as_mut().sort();          } -        if self.required_components.len() == 0 { +        if self.required_components.is_empty() {              self.required_components.extend(ids);              return self;          } @@ -265,7 +267,7 @@ impl_terms_builder! {              ids.as_mut().sort();          } -        if self.excluded_components.len() == 0 { +        if self.excluded_components.is_empty() {              self.excluded_components.extend(ids);              return self;          } @@ -293,10 +295,11 @@ impl_terms_builder! {  impl<const MAX_TERM_CNT: usize> TermsBuilder<MAX_TERM_CNT>  { +    #[must_use]      pub fn build(self) -> Terms<MAX_TERM_CNT>      { -        assert!(self.required_components.is_sorted()); -        assert!(self.excluded_components.is_sorted()); +        debug_assert!(self.required_components.is_sorted()); +        debug_assert!(self.excluded_components.is_sorted());          Terms {              required_components: self.required_components, diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs index 3e72b34..6d65ee0 100644 --- a/ecs/src/query/flexible.rs +++ b/ecs/src/query/flexible.rs @@ -2,13 +2,8 @@  use std::iter::{repeat_n, FlatMap, RepeatN, Zip};  use crate::component::storage::archetype::{Archetype, EntityIter}; -use crate::component::storage::{ -    ArchetypeRefIter, -    ArchetypeSearchTerms, -    Storage as ComponentStorage, -}; +use crate::component::storage::{ArchetypeRefIter, ArchetypeSearchTerms};  use crate::entity::Handle as EntityHandle; -use crate::lock::ReadGuard;  use crate::query::Terms;  use crate::World; @@ -17,7 +12,6 @@ use crate::World;  pub struct Query<'world, const MAX_TERM_CNT: usize>  {      world: &'world World, -    component_storage: ReadGuard<'world, ComponentStorage>,      terms: Terms<MAX_TERM_CNT>,  } @@ -30,6 +24,8 @@ impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>          Iter {              world: self.world,              iter: self +                .world +                .data                  .component_storage                  .search_archetypes(ArchetypeSearchTerms {                      required_components: &self.terms.required_components, @@ -46,15 +42,18 @@ impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>      pub(crate) fn new(world: &'world World, terms: Terms<MAX_TERM_CNT>) -> Self      { -        Self { -            world, -            component_storage: world -                .data -                .component_storage -                .read_nonblock() -                .expect("Failed to acquire read-only component storage lock"), -            terms, -        } +        Self { world, terms } +    } +} + +impl<'query, const MAX_TERM_CNT: usize> IntoIterator for &'query Query<'_, MAX_TERM_CNT> +{ +    type IntoIter = Iter<'query>; +    type Item = EntityHandle<'query>; + +    fn into_iter(self) -> Self::IntoIter +    { +        self.iter()      }  } diff --git a/ecs/src/uid.rs b/ecs/src/uid.rs index 6c97649..feed62c 100644 --- a/ecs/src/uid.rs +++ b/ecs/src/uid.rs @@ -54,8 +54,12 @@ impl Uid          }      } +    /// Returns a new pair UID. +    /// +    /// # Panics +    /// Will panic if either the given relation or target is a pair UID.      #[must_use] -    pub fn new_pair(params: PairParams) -> Self +    pub fn new_pair(params: &PairParams) -> Self      {          assert_ne!(              params.relation.kind(), @@ -102,6 +106,7 @@ impl Uid      ///      /// # Panics      /// Will panic if this `Uid` is not a pair. +    #[must_use]      pub fn relation_component(&self) -> Self      {          assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); @@ -112,6 +117,7 @@ impl Uid          }      } +    #[must_use]      pub fn has_same_relation_as(&self, other: Self) -> bool      {          self.relation() == other.relation() @@ -121,6 +127,7 @@ impl Uid      ///      /// # Panics      /// Will panic if this `Uid` is not a pair. +    #[must_use]      pub fn relation_entity(&self) -> Self      {          assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); @@ -135,6 +142,7 @@ impl Uid      ///      /// # Panics      /// Will panic if this `Uid` is not a pair. +    #[must_use]      pub fn target_component(&self) -> Self      {          assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); @@ -149,6 +157,7 @@ impl Uid      ///      /// # Panics      /// Will panic if this `Uid` is not a pair. +    #[must_use]      pub fn target_entity(&self) -> Self      {          assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair"); @@ -159,7 +168,7 @@ impl Uid          }      } -    fn relation(&self) -> u32 +    fn relation(self) -> u32      {          let Ok(relation) = u32::try_from(self.inner.field_get(RELATION_BITS)) else {              unreachable!("Uid relation does not fit in u32"); diff --git a/ecs/src/util.rs b/ecs/src/util.rs index eb06ab4..9ab4dc6 100644 --- a/ecs/src/util.rs +++ b/ecs/src/util.rs @@ -4,7 +4,7 @@ use std::ops::{BitAnd, Deref};  use hashbrown::HashMap; -pub mod array_vec; +pub(crate) mod array_vec;  pub trait VecExt<Item>  { diff --git a/ecs/src/util/array_vec.rs b/ecs/src/util/array_vec.rs index 648c976..13a0349 100644 --- a/ecs/src/util/array_vec.rs +++ b/ecs/src/util/array_vec.rs @@ -1,4 +1,4 @@ -use std::mem::{transmute, MaybeUninit}; +use std::mem::MaybeUninit;  use std::ops::{Deref, DerefMut};  #[derive(Debug)] @@ -10,16 +10,18 @@ pub struct ArrayVec<Item, const CAPACITY: usize>  impl<Item, const CAPACITY: usize> ArrayVec<Item, CAPACITY>  { -    pub fn new() -> Self +    #[inline] +    #[must_use] +    pub fn len(&self) -> usize      { -        Self::default() +        self.len      }      #[inline]      #[must_use] -    pub fn len(&self) -> usize +    pub fn is_empty(&self) -> bool      { -        self.len +        self.len == 0      }      pub fn push(&mut self, item: Item) @@ -69,7 +71,9 @@ impl<Item, const CAPACITY: usize> AsRef<[Item]> for ArrayVec<Item, CAPACITY>  {      fn as_ref(&self) -> &[Item]      { -        unsafe { transmute::<&[MaybeUninit<Item>], &[Item]>(&self.items[..self.len]) } +        let ptr = &raw const self.items[..self.len]; + +        unsafe { &*(ptr as *const [Item]) }      }  } @@ -77,11 +81,9 @@ impl<Item, const CAPACITY: usize> AsMut<[Item]> for ArrayVec<Item, CAPACITY>  {      fn as_mut(&mut self) -> &mut [Item]      { -        unsafe { -            transmute::<&mut [MaybeUninit<Item>], &mut [Item]>( -                &mut self.items[..self.len], -            ) -        } +        let ptr = &raw mut self.items[..self.len]; + +        unsafe { &mut *(ptr as *mut [Item]) }      }  } | 
