1use std::marker::PhantomData;
2
3use crate::world::UnsafeWorldCell;
4
5use super::{IntoSystem, System, SystemParam, SystemParamItem};
6
7pub struct FunctionSystem<Marker, F> {
8 name: &'static str,
9 func: F,
10 marker: PhantomData<Marker>,
11}
12
13impl<Marker, F> System for FunctionSystem<Marker, F>
14where
15 Marker: 'static,
16 F: SystemParamFunction<Marker>,
17{
18 fn run(&mut self, world: &mut crate::world::World) {
19 let unsafe_world_cell = UnsafeWorldCell::new(world);
20 let params = F::Param::get_param(unsafe_world_cell);
21 self.func.run(params)
22 }
23}
24
25impl<Marker, F> IntoSystem<Marker> for F
26where
27 Marker: 'static,
28 F: SystemParamFunction<Marker>,
29{
30 type System = FunctionSystem<Marker, F>;
31
32 fn into_system(self) -> Self::System {
33 FunctionSystem {
34 name: std::any::type_name::<F>(),
35 func: self,
36 marker: PhantomData,
37 }
38 }
39}
40
41pub trait SystemParamFunction<Marker>: 'static {
42 type Param: SystemParam;
43
44 fn run(&mut self, param_value: SystemParamItem<Self::Param>);
45}
46
47impl<F> SystemParamFunction<fn()> for F
48where
49 F: 'static,
50 for<'a> &'a mut F: FnMut(),
51{
52 type Param = ();
53
54 fn run(&mut self, param_value: SystemParamItem<Self::Param>) {
55 fn call_inner(mut f: impl FnMut()) {
56 f()
57 }
58
59 call_inner(self)
60 }
61}
62
63macro_rules! impl_spf_from {
64 ( $($n:ident),* ) => {
65 #[allow(non_snake_case)]
66 impl<F, $($n,)*> SystemParamFunction<fn($($n,)*)> for F
67 where
68 F: 'static,
69 for<'a> &'a mut F: FnMut($($n,)*) + FnMut($(SystemParamItem<$n>,)*),
70 $($n: SystemParam,)*
71 {
72 type Param = ($($n,)*);
73
74 fn run(&mut self, param_value: SystemParamItem<Self::Param>) {
75 fn call_inner<$($n,)*>(mut f: impl FnMut($($n,)*), $($n: $n,)*) {
76 f($($n,)*)
77 }
78 let ($($n,)*) = param_value;
79 call_inner(self, $($n,)*)
80 }
81 }
82 };
83}
84
85impl_spf_from!(T1);
86impl_spf_from!(T1, T2);
87impl_spf_from!(T1, T2, T3);
88impl_spf_from!(T1, T2, T3, T4);
89impl_spf_from!(T1, T2, T3, T4, T5);
90impl_spf_from!(T1, T2, T3, T4, T5, T6);
91impl_spf_from!(T1, T2, T3, T4, T5, T6, T7);
92impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8);
93impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
94impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
95impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
96impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
97impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
98impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
99impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
100impl_spf_from!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);