From fec7e1a774cde71632a3032253017604b3e1ca14 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 22 Jun 2024 20:00:39 +0200 Subject: feat(ecs): add tuple method to pop the last element --- ecs/src/tuple.rs | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'ecs') 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 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! { + [] + } + }; +} + +macro_rules! elem_by_index { + (overflow) => { + () + }; + + ($index: tt, $self: ident) => { + $self.$index + }; +} + +pub trait Pop: WithoutLast +{ + type LastElem; + + fn pop(self) -> (::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,)*); @@ -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) -> (::Return, Self::LastElem) + { + ( + all_except_last!(start #((self.I))*), + sub!($cnt - 1, elem_by_index, (self)) + ) + } + } }); }; } -- cgit v1.2.3-18-g5258