summaryrefslogtreecommitdiff
path: root/ecs/src/tuple.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/tuple.rs')
-rw-r--r--ecs/src/tuple.rs115
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,)*)
{
}
});