diff options
Diffstat (limited to 'ecs/src/tuple.rs')
-rw-r--r-- | ecs/src/tuple.rs | 115 |
1 files changed, 56 insertions, 59 deletions
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,)*) { } }); |