diff options
author | HampusM <hampus@hampusmat.com> | 2024-12-10 21:48:10 +0100 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-12-13 17:16:34 +0100 |
commit | 9e057e9249fb5a8a9f3b2ba00a993049f733c9dd (patch) | |
tree | 7f8ca6d56438e83cd1d0da2562d18acbd13e5c80 | |
parent | c6de2c7ab9c48223ab307fe0039fae7ab2613e16 (diff) |
refactor(ecs): improve system init param retrieval
-rw-r--r-- | ecs/src/system/stateful.rs | 46 | ||||
-rw-r--r-- | ecs/src/tuple.rs | 115 |
2 files changed, 75 insertions, 86 deletions
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs index 536e6ed..5eae1da 100644 --- a/ecs/src/system/stateful.rs +++ b/ecs/src/system/stateful.rs @@ -1,4 +1,4 @@ -use std::any::{type_name, Any, TypeId}; +use std::any::{Any, TypeId}; use std::collections::HashMap; use std::panic::{RefUnwindSafe, UnwindSafe}; @@ -15,10 +15,9 @@ use crate::system::{ TypeErased, }; use crate::tuple::{ - IntoInOptions as TupleIntoInOptions, Reduce as TupleReduce, - TakeOptionElementResult as TupleTakeOptionElementResult, - WithOptionElements as TupleWithOptionElements, + Tuple, + WithAllElemLtStatic as TupleWithAllElemLtStatic, }; use crate::uid::Uid; use crate::World; @@ -39,9 +38,10 @@ macro_rules! impl_system { Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static, #(TParam~I: Param<'world>,)* #(TParam~I::Input: 'static,)* - (#(TParam~I::Input,)*): TupleReduce<ParamWithInputFilter>, - <(#(TParam~I::Input,)*) as TupleReduce<ParamWithInputFilter>>::Out: - TupleIntoInOptions + (#(TParam~I::Input,)*): TupleReduce< + ParamWithInputFilter, + Out: Tuple<InOptions: TupleWithAllElemLtStatic> + >, { type Input = <(#(TParam~I::Input,)*) as TupleReduce<ParamWithInputFilter>>::Out; @@ -50,35 +50,27 @@ macro_rules! impl_system { { let mut option_input = input.into_in_options(); + let mut index = 0; + #( if TypeId::of::<TParam~I::Input>() != TypeId::of::<()>() { - let input = match option_input.take::<TParam~I::Input>() { - TupleTakeOptionElementResult::Found(input) => input, - TupleTakeOptionElementResult::NotFound => { - panic!( - "Parameter input {} not found", - type_name::<TParam~I::Input>() - ); - } - TupleTakeOptionElementResult::AlreadyTaken => { - panic!( - concat!( - "Parameter {} is already initialized. ", - "System cannot contain multiple inputs with ", - "the same type", - ), - type_name::<TParam~I>() - ); - - } - }; + let input = option_input + .get_mut::<Option<TParam~I::Input>>(index) + .expect("Input element index out of range") + .take() + .expect("Input element is already taken"); TParam~I::initialize( &mut self, input ); + + #[allow(unused_assignments)] + { + index += 1; + } } )* diff --git a/ecs/src/tuple.rs b/ecs/src/tuple.rs index b16160c..def25a0 100644 --- a/ecs/src/tuple.rs +++ b/ecs/src/tuple.rs @@ -1,5 +1,4 @@ use std::any::TypeId; -use std::mem::{transmute_copy, ManuallyDrop}; use paste::paste; use seq_macro::seq; @@ -24,23 +23,22 @@ pub trait Tuple: sealed::Sealed /// The last element of `Self`. type LastElement; + /// Self with all elements wrapped in [`Option`]. + type InOptions: Tuple; + /// Pops the last element from this tuple, returning the new tuple and the popped /// element. fn pop_last(self) -> (Self::WithoutLastElement, Self::LastElement); -} - -/// Used to make all elements of a tuple type wrapped in [`Option`]. -pub trait IntoInOptions -{ - type InOptions: WithOptionElements; + /// Converts this tuple so that all elements are wrapped in [`Option`]. fn into_in_options(self) -> Self::InOptions; } -/// A tuple with all elements wrapped in [`Option`]. -pub trait WithOptionElements +/// A tuple with element types that all have the lifetime `'static`. +pub trait WithAllElemLtStatic: Tuple + sealed::Sealed { - fn take<Element: 'static>(&mut self) -> TakeOptionElementResult<Element>; + /// Returns the element at the given index. + fn get_mut<Element: 'static>(&mut self, index: usize) -> Option<&mut Element>; } /// Using the type system, reduces the elements of a tuple to a single one. Each element @@ -55,22 +53,6 @@ pub trait ReduceElement<Accumulator, Operation> type Return; } -/// The result of trying to [`take`] a element from a implementation of -/// [`WithOptionElements`]. -/// -/// [`take`]: WithOptionElements::take -pub enum TakeOptionElementResult<Element> -{ - /// The element was succesfully taken. - Found(Element), - - /// The element is not a element of the tuple. - NotFound, - - /// The element has already been taken - AlreadyTaken, -} - macro_rules! tuple_reduce_elem_tuple { (overflow) => { () @@ -134,7 +116,7 @@ macro_rules! all_except_last { macro_rules! impl_tuple_traits { ($cnt: tt) => { seq!(I in 0..$cnt { - impl< #(Elem~I,)*> Tuple for (#(Elem~I,)*) + impl<#(Elem~I,)*> Tuple for (#(Elem~I,)*) { type WithElementAtEnd<NewElem> = (#(Elem~I,)* NewElem,); @@ -142,6 +124,8 @@ macro_rules! impl_tuple_traits { type LastElement = sub!($cnt - 1, elem_type_by_index); + type InOptions = (#(Option<Elem~I>,)*); + fn pop_last(self) -> (Self::WithoutLastElement, Self::LastElement) { ( @@ -149,15 +133,6 @@ macro_rules! impl_tuple_traits { sub!($cnt - 1, elem_by_index, (self)) ) } - } - - impl< #(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) - { - } - - impl<#(Element~I: 'static,)*> IntoInOptions for (#(Element~I,)*) - { - type InOptions = (#(Option<Element~I>,)*); fn into_in_options(self) -> Self::InOptions { @@ -166,32 +141,28 @@ macro_rules! impl_tuple_traits { } } - impl<#(Element~I: 'static,)*> WithOptionElements for (#(Option<Element~I>,)*) + impl<#(Elem~I: 'static,)*> WithAllElemLtStatic for (#(Elem~I,)*) { - fn take<Element: 'static>(&mut self) - -> TakeOptionElementResult<Element> + fn get_mut<Element: 'static>(&mut self, index: usize) -> Option<&mut Element> { - #( - if TypeId::of::<Element~I>() == TypeId::of::<Element>() { - let input = match self.I.take() { - Some(input) => ManuallyDrop::new(input), - None => { - return TakeOptionElementResult::AlreadyTaken; - } - }; - - return TakeOptionElementResult::Found( - // SAFETY: It can be transmuted safely since it is the - // same type and the type is 'static - unsafe { transmute_copy(&input) } - ); - } - )* - - TakeOptionElementResult::NotFound + match index { + #( + I => { + assert!(TypeId::of::<Element>() == TypeId::of::<Elem~I>()); + + // SAFETY: It is checked above that the type is correct + Some(unsafe { &mut *(&raw mut self.I).cast::<Element>() }) + } + )* + _ => None + } } } + impl<#(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) + { + } + paste! { impl<Operation, #(Elem~I,)*> Reduce<Operation> for (#(Elem~I,)*) where @@ -213,7 +184,7 @@ seq!(N in 0..16 { }); seq!(I in 0..16 { - impl< #(Elem~I,)*> Tuple for (#(Elem~I,)*) + impl<#(Elem~I,)*> Tuple for (#(Elem~I,)*) { type WithElementAtEnd<NewElem> = (); @@ -221,6 +192,8 @@ seq!(I in 0..16 { type LastElement = Elem15; + type InOptions = (#(Option<Elem~I>,)*); + fn pop_last(self) -> (Self::WithoutLastElement, Self::LastElement) { ( @@ -228,9 +201,33 @@ seq!(I in 0..16 { self.15 ) } + + fn into_in_options(self) -> Self::InOptions + { + #![allow(clippy::unused_unit)] + (#(Some(self.I),)*) + } + } + + impl<#(Elem~I: 'static,)*> WithAllElemLtStatic for (#(Elem~I,)*) + { + fn get_mut<Element: 'static>(&mut self, index: usize) -> Option<&mut Element> + { + match index { + #( + I => { + assert!(TypeId::of::<Element>() == TypeId::of::<Elem~I>()); + + // SAFETY: It is checked above that the type is correct + Some(unsafe { &mut *(&raw mut self.I).cast::<Element>() }) + } + )* + _ => None + } + } } - impl< #(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) + impl<#(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) { } }); |