From fb47933690dfb54206e9f136902671b19ddd34e0 Mon Sep 17 00:00:00 2001 From: HampusM Date: Tue, 22 Apr 2025 18:06:59 +0200 Subject: refactor(ecs): fix clippy lints --- ecs-macros/src/lib.rs | 27 ++++-- ecs/src/actions.rs | 8 +- ecs/src/component.rs | 8 ++ ecs/src/component/storage.rs | 53 +++++------ ecs/src/component/storage/archetype.rs | 23 ++--- ecs/src/entity.rs | 20 +++- ecs/src/lib.rs | 169 ++++++++++++--------------------- ecs/src/pair.rs | 29 +++--- ecs/src/query.rs | 11 ++- ecs/src/query/flexible.rs | 31 +++--- ecs/src/uid.rs | 13 ++- ecs/src/util.rs | 2 +- ecs/src/util/array_vec.rs | 24 ++--- 13 files changed, 204 insertions(+), 214 deletions(-) diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs index a6fdf28..aab8dd2 100644 --- a/ecs-macros/src/lib.rs +++ b/ecs-macros/src/lib.rs @@ -1,3 +1,4 @@ +#![deny(clippy::all, clippy::pedantic)] use std::path::PathBuf as FsPathBuf; use proc_macro::TokenStream; @@ -41,6 +42,13 @@ macro_rules! syn_path_segment { }; } +/// Generates a `Component` implementation. +/// +/// # Panics +/// Will panic if: +/// - Not attributed to a type item +/// - The attributed-to type item is generic +/// - If parsing the user crate's `Cargo.toml` file fails. #[proc_macro_derive(Component, attributes(component))] pub fn component_derive(input: TokenStream) -> TokenStream { @@ -117,6 +125,11 @@ pub fn component_derive(input: TokenStream) -> TokenStream .into() } +/// Generates a `Sole` implementation. +/// +/// # Panics +/// Will panic if not attributed to a type item or if parsing the user crate's +/// `Cargo.toml` file fails. #[proc_macro_derive(Sole, attributes(sole))] pub fn sole_derive(input: TokenStream) -> TokenStream { @@ -189,9 +202,7 @@ impl TypeItem let mut attr: Option<&Attribute> = None; for item_attr in item_attrs { - if attr.is_some() { - panic!("Expected only one {} attribute", attr_ident); - } + assert!(attr.is_none(), "Expected only one {attr_ident} attribute"); if item_attr.path().get_ident()? == attr_ident { attr = Some(item_attr); @@ -354,11 +365,11 @@ impl FromAttribute for ComponentAttribute Ok(Self { handle_type: handle_type - .map(|handle_type| handle_type.into_token_stream()) - .unwrap_or_else(|| Self::default().handle_type), - handle_mut_type: handle_mut_type - .map(|handle_mut_type| handle_mut_type.into_token_stream()) - .unwrap_or_else(|| Self::default().handle_mut_type), + .map_or_else(|| Self::default().handle_type, ToTokens::into_token_stream), + handle_mut_type: handle_mut_type.map_or_else( + || Self::default().handle_mut_type, + ToTokens::into_token_stream, + ), }) } } 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) -> Self + fn new(action_queue: &'world Rc) -> 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, + action_queue: Rc, _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>, 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(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::>(), + 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>, RepeatN>, + MatchingComponentIterFilterFn, + >, + MatchingComponentIterMapFn, +>; + +type InnerMatchingComponentIterB = Zip, OptionIntoIter>; + #[derive(Debug)] pub struct MatchingComponentIter<'archetype> { - inner: Either< - Map< - Filter< - Zip>, RepeatN>, - MatchingComponentIterFilterFn, - >, - MatchingComponentIterMapFn, - >, - Zip, OptionIntoIter>, - >, + inner: Either, 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(&self) -> Option> { 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( &self, ) -> Option> @@ -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(&self, components: Comps, entity_uid: Uid) + pub fn create_entity_with_uid(&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::(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::( + 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::(removed_ent_comp.id()); - } - } - fn add_entity_components( entity_uid: Uid, components: impl IntoIterator, @@ -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>, + component_storage: ComponentStorage, sole_storage: SoleStorage, - action_queue: Arc, + action_queue: Rc, } 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::(), - )), + 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 impl Pair { + #[must_use] pub fn new(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> { 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 Terms } #[derive(Debug, Default)] +#[must_use] pub struct TermsBuilder { required_components: ArrayVec, excluded_components: ArrayVec, } +#[allow(clippy::return_self_not_must_use)] pub trait TermsBuilderInterface { fn with(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 TermsBuilder { + #[must_use] pub fn build(self) -> Terms { - 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, } @@ -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) -> 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 { 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 impl ArrayVec { - 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 AsRef<[Item]> for ArrayVec { fn as_ref(&self) -> &[Item] { - unsafe { transmute::<&[MaybeUninit], &[Item]>(&self.items[..self.len]) } + let ptr = &raw const self.items[..self.len]; + + unsafe { &*(ptr as *const [Item]) } } } @@ -77,11 +81,9 @@ impl AsMut<[Item]> for ArrayVec { fn as_mut(&mut self) -> &mut [Item] { - unsafe { - transmute::<&mut [MaybeUninit], &mut [Item]>( - &mut self.items[..self.len], - ) - } + let ptr = &raw mut self.items[..self.len]; + + unsafe { &mut *(ptr as *mut [Item]) } } } -- cgit v1.2.3-18-g5258