summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs/src/tuple.rs81
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))
+ )
+ }
+ }
});
};
}