1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
use std::marker::PhantomData;
use seq_macro::seq;
use crate::system::{Input, Param as SystemParam, System};
use crate::tuple::{Reduce as TupleReduce, ReduceElement as TupleReduceElement, Tuple};
/// A initializable system.
pub trait Initializable<'world, Impl>: System<'world, Impl>
{
type Inputs;
#[must_use]
fn initialize(self, inputs: Self::Inputs) -> Self;
}
pub trait Param<'world, SystemT>: SystemParam<'world>
{
fn initialize(system: &mut SystemT, input: Self::Input);
}
pub struct ParamTupleFilter<'world, SystemT>
{
_pd: PhantomData<(&'world (), SystemT)>,
}
impl<'world, SystemT, ParamT, Accumulator>
TupleReduceElement<Accumulator, ParamTupleFilter<'world, SystemT>> for ParamT
where
ParamT: SystemParam<
'world,
Input: AppendInitializableParam<'world, Accumulator, ParamT, SystemT>,
>,
Accumulator: Tuple,
{
type Return = <ParamT::Input as AppendInitializableParam<
'world,
Accumulator,
ParamT,
SystemT,
>>::Return;
}
pub trait AppendInitializableParam<'world, Accumulator, ParamT, SystemT>
{
type Return;
}
impl<'world, InputT, ParamT, Accumulator, SystemT>
AppendInitializableParam<'world, Accumulator, ParamT, SystemT> for InputT
where
InputT: Input,
Accumulator: Tuple,
ParamT: Param<'world, SystemT>,
{
type Return = Accumulator::WithElementAtEnd<ParamT>;
}
impl<ParamT, Accumulator, SystemT>
AppendInitializableParam<'_, Accumulator, ParamT, SystemT> for ()
where
Accumulator: Tuple,
{
type Return = Accumulator;
}
pub trait ParamTuple<'world, SystemT>
{
type Inputs;
fn initialize_all(system: &mut SystemT, inputs: Self::Inputs);
}
macro_rules! impl_initializable_param_tuple {
($c: tt) => {
seq!(I in 0..$c {
impl<'world, SystemT, #(Param~I,)*> ParamTuple<'world, SystemT>
for (#(Param~I,)*)
where
#(Param~I: Param<'world, SystemT>,)*
{
type Inputs = (#(Param~I::Input,)*);
fn initialize_all(
system: &mut SystemT,
inputs: Self::Inputs,
) {
#(
<Param~I as Param<'world, SystemT>>::initialize(
system,
inputs.I
);
)*
}
}
});
};
}
seq!(C in 1..16 {
impl_initializable_param_tuple!(C);
});
impl<SystemT> ParamTuple<'_, SystemT> for ()
{
type Inputs = ();
fn initialize_all(_system: &mut SystemT, _inputs: Self::Inputs) {}
}
/// A tuple of system parameters that may or may not be initializable.
pub trait MaybeInitializableParamTuple<'world, SystemT>
{
/// A tuple of the inputs of the initializable system parameters in this tuple.
type Inputs;
fn init_initializable(system: &mut SystemT, inputs: Self::Inputs);
}
impl<'world, SystemT, Params> MaybeInitializableParamTuple<'world, SystemT> for Params
where
Params:
TupleReduce<ParamTupleFilter<'world, SystemT>, Out: ParamTuple<'world, SystemT>>,
{
type Inputs = <Params::Out as ParamTuple<'world, SystemT>>::Inputs;
fn init_initializable(system: &mut SystemT, inputs: Self::Inputs)
{
Params::Out::initialize_all(system, inputs);
}
}
|