diff options
author | HampusM <hampus@hampusmat.com> | 2024-06-22 20:00:39 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2024-06-22 20:00:39 +0200 |
commit | fec7e1a774cde71632a3032253017604b3e1ca14 (patch) | |
tree | 54fcc9a8d8a03f61e47df183ed5b745503f73d90 /ecs/src | |
parent | f07c7ca188fb5e99133b7b2e371c1949b0a902d5 (diff) |
feat(ecs): add tuple method to pop the last element
Diffstat (limited to 'ecs/src')
-rw-r--r-- | ecs/src/tuple.rs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/ecs/src/tuple.rs b/ecs/src/tuple.rs index 682c11d..1434592 100644 --- a/ecs/src/tuple.rs +++ b/ecs/src/tuple.rs @@ -11,6 +11,14 @@ pub trait With<OtherElem> 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; +} + /// Used to make all elements of a tuple type wrapped in [`Option`]. pub trait IntoInOptions { @@ -65,6 +73,61 @@ macro_rules! tuple_reduce_elem_tuple { }; } +macro_rules! elem_type_by_index { + (overflow) => { + () + }; + + ($index: tt) => { + paste! { + [<Elem $index>] + } + }; +} + +macro_rules! elem_by_index { + (overflow) => { + () + }; + + ($index: tt, $self: ident) => { + $self.$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)*) + }; + + (@[$($included_elem: ident,)*] $elem: ident $($rest: tt)+) => { + all_except_last!(@[$($included_elem,)* $elem,] $($rest)*) + }; + + (@[$($included_elem: expr,)*] ($elem: expr) $($rest: tt)+) => { + all_except_last!(@[$($included_elem,)* $elem,] $($rest)*) + }; + + (@[$($included_elem: ident,)*] $elem: ident) => { + ($($included_elem,)*) + }; + + (@[$($included_elem: expr,)*] $elem: expr) => { + ($($included_elem,)*) + }; + + (@[]) => { + () + }; +} + macro_rules! impl_tuple_traits { ($cnt: tt) => { seq!(I in 0..$cnt { @@ -73,6 +136,11 @@ macro_rules! impl_tuple_traits { type With = (#(Elem~I,)* OtherElem,); } + impl<#(Elem~I,)*> WithoutLast for (#(Elem~I,)*) + { + type Return = all_except_last!(start #(Elem~I)*); + } + impl<#(Element~I: 'static,)*> IntoInOptions for (#(Element~I,)*) { type InOptions = (#(Option<Element~I>,)*); @@ -122,6 +190,19 @@ 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)) + ) + } + } }); }; } |