diff options
Diffstat (limited to 'ecs/src/tuple.rs')
-rw-r--r-- | ecs/src/tuple.rs | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/ecs/src/tuple.rs b/ecs/src/tuple.rs index 1434592..b16160c 100644 --- a/ecs/src/tuple.rs +++ b/ecs/src/tuple.rs @@ -5,18 +5,28 @@ use paste::paste; use seq_macro::seq; use util_macros::sub; -/// Used to append a element to a tuple type. -pub trait With<OtherElem> +pub trait Tuple: sealed::Sealed { - type With; -} - -/// Used to remove the last element of a tuple type. -/// -/// For example: `(u32, String, PathBuf)` becomes `(u32, String)`. -pub trait WithoutLast -{ - type Return; + /// `Self` with the given type added as the last element. + /// + /// `(String, i32, u8)::WithElementAtEnd<Path> = (String, i32, u8, Path)` + /// + /// # Important note + /// If `Self` has 16 elements, this will be `()`. The reason for this is that the + /// `Tuple` trait is only implemented for tuples with up to and including 16 elements. + type WithElementAtEnd<NewElem>: Tuple; + + /// `Self` without the last element. + /// + /// `(u16, AtomicU8)::WithoutLastElement = (u16,)` + type WithoutLastElement: Tuple; + + /// The last element of `Self`. + type LastElement; + + /// 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`]. @@ -95,13 +105,6 @@ macro_rules! elem_by_index { }; } -pub trait Pop: WithoutLast -{ - type LastElem; - - fn pop(self) -> (<Self as WithoutLast>::Return, Self::LastElem); -} - macro_rules! all_except_last { (start $($rest: tt)*) => { all_except_last!(@[] $($rest)*) @@ -131,14 +134,25 @@ macro_rules! all_except_last { macro_rules! impl_tuple_traits { ($cnt: tt) => { seq!(I in 0..$cnt { - impl<OtherElem, #(Elem~I,)*> With<OtherElem> for (#(Elem~I,)*) + impl< #(Elem~I,)*> Tuple for (#(Elem~I,)*) { - type With = (#(Elem~I,)* OtherElem,); + type WithElementAtEnd<NewElem> = (#(Elem~I,)* NewElem,); + + type WithoutLastElement = all_except_last!(start #(Elem~I)*); + + type LastElement = sub!($cnt - 1, elem_type_by_index); + + fn pop_last(self) -> (Self::WithoutLastElement, Self::LastElement) + { + ( + all_except_last!(start #((self.I))*), + sub!($cnt - 1, elem_by_index, (self)) + ) + } } - impl<#(Elem~I,)*> WithoutLast for (#(Elem~I,)*) + impl< #(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) { - type Return = all_except_last!(start #(Elem~I)*); } impl<#(Element~I: 'static,)*> IntoInOptions for (#(Element~I,)*) @@ -190,19 +204,6 @@ macro_rules! impl_tuple_traits { type Out = sub!($cnt - 1, tuple_reduce_elem_tuple); } } - - impl<#(Elem~I,)*> Pop for (#(Elem~I,)*) - { - type LastElem = sub!($cnt - 1, elem_type_by_index); - - fn pop(self) -> (<Self as WithoutLast>::Return, Self::LastElem) - { - ( - all_except_last!(start #((self.I))*), - sub!($cnt - 1, elem_by_index, (self)) - ) - } - } }); }; } @@ -210,3 +211,31 @@ macro_rules! impl_tuple_traits { seq!(N in 0..16 { impl_tuple_traits!(N); }); + +seq!(I in 0..16 { + impl< #(Elem~I,)*> Tuple for (#(Elem~I,)*) + { + type WithElementAtEnd<NewElem> = (); + + type WithoutLastElement = all_except_last!(start #(Elem~I)*); + + type LastElement = Elem15; + + fn pop_last(self) -> (Self::WithoutLastElement, Self::LastElement) + { + ( + all_except_last!(start #((self.I))*), + self.15 + ) + } + } + + impl< #(Elem~I,)*> sealed::Sealed for (#(Elem~I,)*) + { + } +}); + +mod sealed +{ + pub trait Sealed {} +} |