From bef61b765de52d14a52c3df86f8b3766846be272 Mon Sep 17 00:00:00 2001
From: HampusM <hampus@hampusmat.com>
Date: Fri, 7 Jun 2024 19:55:47 +0200
Subject: refactor(ecs): make tuple reduce operation more generic

---
 ecs/src/actions.rs         |  3 +--
 ecs/src/query.rs           |  3 +--
 ecs/src/sole.rs            |  3 +--
 ecs/src/system.rs          | 11 ++++++++++-
 ecs/src/system/stateful.rs | 20 ++++++++++++++------
 ecs/src/tuple.rs           | 24 ++++++++++--------------
 6 files changed, 37 insertions(+), 27 deletions(-)

(limited to 'ecs/src')

diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs
index 9d3eb4e..4cbd515 100644
--- a/ecs/src/actions.rs
+++ b/ecs/src/actions.rs
@@ -5,7 +5,6 @@ use std::sync::{Arc, Weak};
 use crate::component::{Component, Sequence as ComponentSequence};
 use crate::lock::{Lock, WriteGuard};
 use crate::system::{NoInitParamFlag, Param as SystemParam, System};
-use crate::tuple::ReduceNoOp as TupleReduceNoOp;
 use crate::{ActionQueue, WorldData};
 
 /// Used to to queue up actions for a [`World`] to perform.
@@ -56,7 +55,7 @@ impl<'world> Actions<'world>
 unsafe impl<'world> SystemParam<'world> for Actions<'world>
 {
     type Flags = NoInitParamFlag;
-    type Input = TupleReduceNoOp;
+    type Input = ();
 
     fn initialize<SystemImpl>(
         _system: &mut impl System<'world, SystemImpl>,
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index dae451a..88ca180 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -13,7 +13,6 @@ use crate::system::{
     Param as SystemParam,
     System,
 };
-use crate::tuple::ReduceNoOp as TupleReduceNoOp;
 use crate::{ComponentStorage, WorldData};
 
 #[derive(Debug)]
@@ -83,7 +82,7 @@ where
     Comps: ComponentSequence,
 {
     type Flags = NoInitSystemParamFlag;
-    type Input = TupleReduceNoOp;
+    type Input = ();
 
     fn initialize<SystemImpl>(
         _system: &mut impl System<'world, SystemImpl>,
diff --git a/ecs/src/sole.rs b/ecs/src/sole.rs
index 332b5f5..39f65a7 100644
--- a/ecs/src/sole.rs
+++ b/ecs/src/sole.rs
@@ -6,7 +6,6 @@ use std::sync::{Arc, Weak};
 
 use crate::lock::{Lock, WriteGuard};
 use crate::system::{NoInitParamFlag, Param as SystemParam, System};
-use crate::tuple::ReduceNoOp as TupleReduceNoOp;
 use crate::type_name::TypeName;
 use crate::WorldData;
 
@@ -94,7 +93,7 @@ where
     SoleT: Sole,
 {
     type Flags = NoInitParamFlag;
-    type Input = TupleReduceNoOp;
+    type Input = ();
 
     fn initialize<SystemImpl>(
         _system: &mut impl System<'world, SystemImpl>,
diff --git a/ecs/src/system.rs b/ecs/src/system.rs
index 6846a16..47872a6 100644
--- a/ecs/src/system.rs
+++ b/ecs/src/system.rs
@@ -186,13 +186,22 @@ pub struct NoInitParamFlag {}
 /// A type which can be used as input to a [`System`].
 pub trait Input: 'static {}
 
-impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator> for InputT
+/// Component tuple reducing operation to get the parameters that takes input.
+pub struct ParamWithInputFilter;
+
+impl<InputT: Input, Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter>
+    for InputT
 where
     Accumulator: TupleWith<Self>,
 {
     type Return = Accumulator::With;
 }
 
+impl<Accumulator> TupleReduceElement<Accumulator, ParamWithInputFilter> for ()
+{
+    type Return = Accumulator;
+}
+
 #[derive(Debug)]
 pub struct ComponentRefMut<'a, ComponentT: Component>
 {
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs
index e74c0ee..6c0b554 100644
--- a/ecs/src/system/stateful.rs
+++ b/ecs/src/system/stateful.rs
@@ -7,11 +7,17 @@ use seq_macro::seq;
 use crate::component::Component;
 use crate::lock::Lock;
 use crate::system::util::check_params_are_compatible;
-use crate::system::{ComponentRefMut, Into as IntoSystem, Param, System, TypeErased};
+use crate::system::{
+    ComponentRefMut,
+    Into as IntoSystem,
+    Param,
+    ParamWithInputFilter,
+    System,
+    TypeErased,
+};
 use crate::tuple::{
     IntoInOptions as TupleIntoInOptions,
     Reduce as TupleReduce,
-    ReduceNoOp as TupleReduceNoOp,
     TakeOptionElementResult as TupleTakeOptionElementResult,
     WithOptionElements as TupleWithOptionElements,
 };
@@ -33,10 +39,12 @@ macro_rules! impl_system {
                 Func: Fn(#(TParam~I,)*) + Copy + RefUnwindSafe + UnwindSafe + 'static,
                 #(TParam~I: Param<'world>,)*
                 #(TParam~I::Input: 'static,)*
-                (#(TParam~I::Input,)*): TupleReduce,
-                <(#(TParam~I::Input,)*) as TupleReduce>::Out: TupleIntoInOptions
+                (#(TParam~I::Input,)*): TupleReduce<ParamWithInputFilter>,
+                <(#(TParam~I::Input,)*) as TupleReduce<ParamWithInputFilter>>::Out:
+                    TupleIntoInOptions
             {
-                type Input = <(#(TParam~I::Input,)*) as TupleReduce>::Out;
+                type Input =
+                    <(#(TParam~I::Input,)*) as TupleReduce<ParamWithInputFilter>>::Out;
 
                 fn initialize(mut self, input: Self::Input) -> Self
                 {
@@ -44,7 +52,7 @@ macro_rules! impl_system {
 
                     #(
                         if TypeId::of::<TParam~I::Input>() !=
-                            TypeId::of::<TupleReduceNoOp>()
+                            TypeId::of::<()>()
                         {
                             let input = match option_input.take::<TParam~I::Input>() {
                                 TupleTakeOptionElementResult::Found(input) => input,
diff --git a/ecs/src/tuple.rs b/ecs/src/tuple.rs
index 5ed8993..682c11d 100644
--- a/ecs/src/tuple.rs
+++ b/ecs/src/tuple.rs
@@ -27,12 +27,12 @@ pub trait WithOptionElements
 
 /// Using the type system, reduces the elements of a tuple to a single one. Each element
 /// determines itself how it is handled.
-pub trait Reduce
+pub trait Reduce<Operation>
 {
     type Out;
 }
 
-pub trait ReduceElement<Accumulator>
+pub trait ReduceElement<Accumulator, Operation>
 {
     type Return;
 }
@@ -53,15 +53,6 @@ pub enum TakeOptionElementResult<Element>
     AlreadyTaken,
 }
 
-/// Zero-sized struct implementing [`ReduceElement`] and just returns the accumulator.
-#[derive(Debug, Clone, Copy)]
-pub struct ReduceNoOp;
-
-impl<Accumulator> ReduceElement<Accumulator> for ReduceNoOp
-{
-    type Return = Accumulator;
-}
-
 macro_rules! tuple_reduce_elem_tuple {
     (overflow) => {
         ()
@@ -77,7 +68,8 @@ macro_rules! tuple_reduce_elem_tuple {
 macro_rules! impl_tuple_traits {
     ($cnt: tt) => {
         seq!(I in 0..$cnt {
-            impl<OtherElem, #(Elem~I,)*> With<OtherElem> for (#(Elem~I,)*) {
+            impl<OtherElem, #(Elem~I,)*> With<OtherElem> for (#(Elem~I,)*)
+            {
                 type With = (#(Elem~I,)* OtherElem,);
             }
 
@@ -119,9 +111,13 @@ macro_rules! impl_tuple_traits {
             }
 
             paste! {
-                impl<#(Elem~I,)*> Reduce for (#(Elem~I,)*)
+                impl<Operation, #(Elem~I,)*> Reduce<Operation> for (#(Elem~I,)*)
                 where
-                    #(Elem~I: ReduceElement<sub!(I - 1, tuple_reduce_elem_tuple)>,)*
+                    #(
+                        Elem~I: ReduceElement<
+                            sub!(I - 1, tuple_reduce_elem_tuple), Operation
+                        >,
+                    )*
                 {
                     type Out = sub!($cnt - 1, tuple_reduce_elem_tuple);
                 }
-- 
cgit v1.2.3-18-g5258