swamp_system/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use core::marker::PhantomData;
6use swamp_system_state::State;
7
8// Systems
9pub trait System: 'static {
10    fn run(&self, world: &mut State);
11}
12
13/// Convert to system (to create a trait object)
14pub trait IntoSystem<Params> {
15    type System: System;
16
17    fn into_system(self) -> Self::System;
18}
19
20/// Convert any function with only system params into a system
21impl<F, Params: SystemParam> IntoSystem<Params> for F
22where
23    F: SystemParamFunction<Params>,
24{
25    type System = FunctionSystem<F, Params>;
26
27    fn into_system(self) -> Self::System {
28        FunctionSystem {
29            system: self,
30            params: PhantomData,
31        }
32    }
33}
34
35/// Wraps a system with params
36pub struct FunctionSystem<F: 'static, Params: SystemParam> {
37    system: F,
38    params: PhantomData<Params>,
39}
40
41/// Implement `System` for the `FunctionSystem` wrapper
42impl<F, Params: SystemParam> System for FunctionSystem<F, Params>
43where
44    F: SystemParamFunction<Params>,
45{
46    fn run(&self, state: &mut State) {
47        SystemParamFunction::run(&self.system, state);
48    }
49}
50
51/// A function with only `SystemParam`, which is the only thing that is supported (and unit function)
52trait SystemParamFunction<Params: SystemParam>: 'static {
53    fn run(&self, state: &mut State);
54}
55
56/// Support for unit function, for convenience
57impl<F> SystemParamFunction<()> for F
58where
59    F: Fn() + 'static,
60{
61    fn run(&self, _state: &mut State) {
62        self(); // We don't need state, since we are just calling without any parameter
63    }
64}
65
66/// implement `SystemParamFunction` for function with one parameter
67impl<F, P1: SystemParam<Item = P1>> SystemParamFunction<(P1,)> for F
68where
69    F: Fn(P1) + 'static,
70{
71    fn run(&self, world: &mut State) {
72        self(P1::fetch(world));
73    }
74}
75
76/// implement `SystemParamFunction` for function with two parameters
77impl<F, P1: SystemParam<Item = P1>, P2: SystemParam<Item = P2>> SystemParamFunction<(P1, P2)> for F
78where
79    F: Fn(P1, P2) + 'static,
80{
81    fn run(&self, world: &mut State) {
82        let v1 = P1::fetch(world);
83        let v2 = P2::fetch(world);
84        self(v1, v2);
85    }
86}
87
88/// implement `SystemParamFunction` for function with three parameters
89impl<F, P1: SystemParam<Item = P1>, P2: SystemParam<Item = P2>, P3: SystemParam<Item = P3>>
90    SystemParamFunction<(P1, P2, P3)> for F
91where
92    F: Fn(P1, P2, P3) + 'static,
93{
94    fn run(&self, world: &mut State) {
95        let v1 = P1::fetch(world);
96        let v2 = P2::fetch(world);
97        let v3 = P3::fetch(world);
98        self(v1, v2, v3);
99    }
100}
101
102/// implement `SystemParamFunction` for function with four parameters
103impl<
104        F,
105        P1: SystemParam<Item = P1>,
106        P2: SystemParam<Item = P2>,
107        P3: SystemParam<Item = P3>,
108        P4: SystemParam<Item = P4>,
109    > SystemParamFunction<(P1, P2, P3, P4)> for F
110where
111    F: Fn(P1, P2, P3, P4) + 'static,
112{
113    fn run(&self, world: &mut State) {
114        let v1 = P1::fetch(world);
115        let v2 = P2::fetch(world);
116        let v3 = P3::fetch(world);
117        let v4 = P4::fetch(world);
118        self(v1, v2, v3, v4);
119    }
120}
121
122/// implement `SystemParamFunction` for function with five parameters
123impl<
124        F,
125        P1: SystemParam<Item = P1>,
126        P2: SystemParam<Item = P2>,
127        P3: SystemParam<Item = P3>,
128        P4: SystemParam<Item = P4>,
129        P5: SystemParam<Item = P5>,
130    > SystemParamFunction<(P1, P2, P3, P4, P5)> for F
131where
132    F: Fn(P1, P2, P3, P4, P5) + 'static,
133{
134    fn run(&self, world: &mut State) {
135        let v1 = P1::fetch(world);
136        let v2 = P2::fetch(world);
137        let v3 = P3::fetch(world);
138        let v4 = P4::fetch(world);
139        let v5 = P5::fetch(world);
140        self(v1, v2, v3, v4, v5);
141    }
142}
143
144/// implement `SystemParamFunction` for function with six parameters
145impl<
146        F,
147        P1: SystemParam<Item = P1>,
148        P2: SystemParam<Item = P2>,
149        P3: SystemParam<Item = P3>,
150        P4: SystemParam<Item = P4>,
151        P5: SystemParam<Item = P5>,
152        P6: SystemParam<Item = P6>,
153    > SystemParamFunction<(P1, P2, P3, P4, P5, P6)> for F
154where
155    F: Fn(P1, P2, P3, P4, P5, P6) + 'static,
156{
157    fn run(&self, world: &mut State) {
158        let v1 = P1::fetch(world);
159        let v2 = P2::fetch(world);
160        let v3 = P3::fetch(world);
161        let v4 = P4::fetch(world);
162        let v5 = P5::fetch(world);
163        let v6 = P6::fetch(world);
164        self(v1, v2, v3, v4, v5, v6);
165    }
166}
167
168/// implement `SystemParamFunction` for function with seven parameters
169impl<
170        F,
171        P1: SystemParam<Item = P1>,
172        P2: SystemParam<Item = P2>,
173        P3: SystemParam<Item = P3>,
174        P4: SystemParam<Item = P4>,
175        P5: SystemParam<Item = P5>,
176        P6: SystemParam<Item = P6>,
177        P7: SystemParam<Item = P7>,
178    > SystemParamFunction<(P1, P2, P3, P4, P5, P6, P7)> for F
179where
180    F: Fn(P1, P2, P3, P4, P5, P6, P7) + 'static,
181{
182    fn run(&self, world: &mut State) {
183        let v1 = P1::fetch(world);
184        let v2 = P2::fetch(world);
185        let v3 = P3::fetch(world);
186        let v4 = P4::fetch(world);
187        let v5 = P5::fetch(world);
188        let v6 = P6::fetch(world);
189        let v7 = P7::fetch(world);
190        self(v1, v2, v3, v4, v5, v6, v7);
191    }
192}
193
194/// implement `SystemParamFunction` for function with eight parameters
195impl<
196        F,
197        P1: SystemParam<Item = P1>,
198        P2: SystemParam<Item = P2>,
199        P3: SystemParam<Item = P3>,
200        P4: SystemParam<Item = P4>,
201        P5: SystemParam<Item = P5>,
202        P6: SystemParam<Item = P6>,
203        P7: SystemParam<Item = P7>,
204        P8: SystemParam<Item = P8>,
205    > SystemParamFunction<(P1, P2, P3, P4, P5, P6, P7, P8)> for F
206where
207    F: Fn(P1, P2, P3, P4, P5, P6, P7, P8) + 'static,
208{
209    fn run(&self, world: &mut State) {
210        let v1 = P1::fetch(world);
211        let v2 = P2::fetch(world);
212        let v3 = P3::fetch(world);
213        let v4 = P4::fetch(world);
214        let v5 = P5::fetch(world);
215        let v6 = P6::fetch(world);
216        let v7 = P7::fetch(world);
217        let v8 = P8::fetch(world);
218        self(v1, v2, v3, v4, v5, v6, v7, v8);
219    }
220}
221
222/// Abstraction of a parameter for a system function
223pub trait SystemParam: 'static {
224    type Item;
225
226    fn fetch(world: &mut State) -> Self::Item;
227}
228
229impl SystemParam for () {
230    type Item = ();
231
232    fn fetch(_world: &mut State) -> Self::Item {
233        // it is easy to fetch, it is nothing `()`
234    }
235}
236
237/// implement one parameter for a `SystemParam`
238impl<T1> SystemParam for (T1,)
239where
240    T1: SystemParam,
241{
242    type Item = (T1::Item,);
243
244    fn fetch(world: &mut State) -> Self::Item {
245        (T1::fetch(world),)
246    }
247}
248
249/// implement two parameters for a `SystemParam`
250impl<T1, T2> SystemParam for (T1, T2)
251where
252    T1: SystemParam,
253    T2: SystemParam,
254{
255    type Item = (T1::Item, T2::Item);
256
257    fn fetch(world: &mut State) -> Self::Item {
258        (T1::fetch(world), T2::fetch(world))
259    }
260}
261
262/// implement three parameters for a `SystemParam`
263impl<T1, T2, T3> SystemParam for (T1, T2, T3)
264where
265    T1: SystemParam,
266    T2: SystemParam,
267    T3: SystemParam,
268{
269    type Item = (T1::Item, T2::Item, T3::Item);
270
271    fn fetch(world: &mut State) -> Self::Item {
272        (T1::fetch(world), T2::fetch(world), T3::fetch(world))
273    }
274}
275
276/// implement four parameters for a `SystemParam`
277impl<T1, T2, T3, T4> SystemParam for (T1, T2, T3, T4)
278where
279    T1: SystemParam,
280    T2: SystemParam,
281    T3: SystemParam,
282    T4: SystemParam,
283{
284    type Item = (T1::Item, T2::Item, T3::Item, T4::Item);
285
286    fn fetch(world: &mut State) -> Self::Item {
287        (
288            T1::fetch(world),
289            T2::fetch(world),
290            T3::fetch(world),
291            T4::fetch(world),
292        )
293    }
294}
295
296/// implement five parameters for a `SystemParam`
297impl<T1, T2, T3, T4, T5> SystemParam for (T1, T2, T3, T4, T5)
298where
299    T1: SystemParam,
300    T2: SystemParam,
301    T3: SystemParam,
302    T4: SystemParam,
303    T5: SystemParam,
304{
305    type Item = (T1::Item, T2::Item, T3::Item, T4::Item, T5::Item);
306
307    fn fetch(world: &mut State) -> Self::Item {
308        (
309            T1::fetch(world),
310            T2::fetch(world),
311            T3::fetch(world),
312            T4::fetch(world),
313            T5::fetch(world),
314        )
315    }
316}
317
318/// implement six parameters for a `SystemParam`
319impl<T1, T2, T3, T4, T5, T6> SystemParam for (T1, T2, T3, T4, T5, T6)
320where
321    T1: SystemParam,
322    T2: SystemParam,
323    T3: SystemParam,
324    T4: SystemParam,
325    T5: SystemParam,
326    T6: SystemParam,
327{
328    type Item = (T1::Item, T2::Item, T3::Item, T4::Item, T5::Item, T6::Item);
329
330    fn fetch(world: &mut State) -> Self::Item {
331        (
332            T1::fetch(world),
333            T2::fetch(world),
334            T3::fetch(world),
335            T4::fetch(world),
336            T5::fetch(world),
337            T6::fetch(world),
338        )
339    }
340}
341
342/// implement seven parameters for a `SystemParam`
343impl<T1, T2, T3, T4, T5, T6, T7> SystemParam for (T1, T2, T3, T4, T5, T6, T7)
344where
345    T1: SystemParam,
346    T2: SystemParam,
347    T3: SystemParam,
348    T4: SystemParam,
349    T5: SystemParam,
350    T6: SystemParam,
351    T7: SystemParam,
352{
353    type Item = (
354        T1::Item,
355        T2::Item,
356        T3::Item,
357        T4::Item,
358        T5::Item,
359        T6::Item,
360        T7::Item,
361    );
362
363    fn fetch(world: &mut State) -> Self::Item {
364        (
365            T1::fetch(world),
366            T2::fetch(world),
367            T3::fetch(world),
368            T4::fetch(world),
369            T5::fetch(world),
370            T6::fetch(world),
371            T7::fetch(world),
372        )
373    }
374}
375
376/// implement seven parameters for a `SystemParam`
377impl<T1, T2, T3, T4, T5, T6, T7, T8> SystemParam for (T1, T2, T3, T4, T5, T6, T7, T8)
378where
379    T1: SystemParam,
380    T2: SystemParam,
381    T3: SystemParam,
382    T4: SystemParam,
383    T5: SystemParam,
384    T6: SystemParam,
385    T7: SystemParam,
386    T8: SystemParam,
387{
388    type Item = (
389        T1::Item,
390        T2::Item,
391        T3::Item,
392        T4::Item,
393        T5::Item,
394        T6::Item,
395        T7::Item,
396        T8::Item,
397    );
398
399    fn fetch(world: &mut State) -> Self::Item {
400        (
401            T1::fetch(world),
402            T2::fetch(world),
403            T3::fetch(world),
404            T4::fetch(world),
405            T5::fetch(world),
406            T6::fetch(world),
407            T7::fetch(world),
408            T8::fetch(world),
409        )
410    }
411}