1use crate::*;
2
3pub struct System {
7 pub(crate) initialize: Box<dyn Fn(&mut World) + Send>,
8 pub(crate) lock:
9 Box<dyn Fn(*const World, *mut Vec<Box<dyn RefLifetime>>) -> SystemResult + Send>,
10 pub(crate) run_fn: Box<dyn FnMut(&World) -> SystemResult + Send>,
11}
12
13impl System {
14 pub fn initialize(&self, world: &mut World) {
20 (self.initialize)(world)
21 }
22 pub fn run(&mut self, world: &World) -> SystemResult {
24 (self.run_fn)(world)
25 }
26}
27
28pub trait IntoSystem<R> {
39 fn system(self) -> System;
40}
41
42macro_rules! impl_system {
43 ($($id:ident,)* $(&mut $idmut:ident,)*) => {
44 impl<$($id: Send + Sync,)* $($idmut: Send + Sync,)* F> IntoSystem<($(&$id,)* $(&mut $idmut,)*)> for F
45 where
46 $($id: Default+'static,)*
47 $($idmut: Default+'static,)*
48 F: Fn($(&$id,)* $(&mut $idmut,)*) -> SystemResult + 'static + Send,
49 {
50 fn system(self) -> System {
51 System {
52 initialize: Box::new(|_world: &mut World| {
53 $(_world.initialize::<$id>();)*
54 $(_world.initialize::<$idmut>();)*
55 }),
56 lock: Box::new(|_world: *const World, _locked: *mut Vec<Box<dyn RefLifetime>>| {
57 $(unsafe {(&mut *_locked).push(Box::new((*_world).get::<$id>()?))};)*
61 $(unsafe {(&mut *_locked).push(Box::new((*_world).get_mut::<$idmut>()?))};)*
62 Ok(())
63 }),
64 run_fn: Box::new(move |_world: &World| {
65 self($(&*_world.get::<$id>()?,)* $(&mut *_world.get_mut::<$idmut>()?),*)
66 }),
67 }
68 }
69 }
70 }
71}
72
73macro_rules! impl_system_muts {
74 ($($processed:ident),*$(,)?;) => {
75 impl_system!($(&mut $processed,)*);
76 };
77 ($($processed:ident),*$(,)?; $head:ident, $($tail:ident,)*) => {
78 impl_system!($($tail,)* $head, $(&mut $processed,)*);
79 impl_system_muts!($($processed,)* $head; $($tail,)*);
80 }
81}
82macro_rules! impl_systems {
83 () => {};
85 ($head:ident, $($idents:ident,)*) => {
86 impl_system_muts!(; $head, $($idents,)*);
88 impl_systems!($($idents,)*);
89 }
90}
91
92impl_system!();
93#[cfg(not(feature="big_systems"))]
94impl_systems!(A, B, C, D, E, G, H, I, J, K, L, M,);
95#[cfg(feature="big_systems")]
97impl_systems!(A, B, C, D, E, G, H, I, J, K, L, M, O, P, Q, R, S, T, U, V, W,);
103
104#[cfg(test)]
105mod tests {
106 use crate::*;
107 use wasm_bindgen_test::*;
108
109 #[test]
110 #[wasm_bindgen_test]
111 fn convert_system() {
112 let _ = generic::<u32>.system();
113 fn tmp(_var1: &u32, _var2: &u64, _var3: &mut i32, _var4: &mut i64) -> SystemResult {
114 Ok(())
115 }
116 fn tmp2(
119 _var1: &u32,
120 _var2: &u64,
121 _var3: &mut i32,
122 _var4: &mut i64,
123 _var5: &mut i64,
124 _var6: &mut i64,
125 _var7: &mut i64,
126 _var8: &mut i64,
127 _var9: &mut i64,
128 _var10: &mut i64,
129 _var11: &mut i64,
130 _var12: &mut i64,
131 ) -> SystemResult {
132 Ok(())
133 }
134 let _ = tmp.system();
135 let _ = tmp2.system();
136 }
137
138 #[test]
139 #[wasm_bindgen_test]
140 fn system_is_send() {
141 let x = 6;
142 send(
143 (move |_var1: &u32| {
144 let _y = x;
145 Ok(())
146 })
147 .system(),
148 );
149 send((|| Ok(())).system());
150 send(sys.system());
151 }
152
153 fn sys(_var1: &u32) -> SystemResult {
154 Ok(())
155 }
156 fn generic<T>(_t: &T) -> SystemResult {
157 Ok(())
158 }
159 fn send<T: Send>(_t: T) {}
160
161 #[test]
162 #[wasm_bindgen_test]
163 fn manual_system_run() {
164 let mut world = World::default();
165 world.initialize::<u32>();
166 generic::<u32>.system().run(&world).unwrap();
167 }
168
169 #[test]
170 #[wasm_bindgen_test]
171 fn system_replace_resource() {
172 #[derive(Default)]
173 pub struct A;
174 #[derive(Default)]
175 pub struct B {
176 x: u32,
177 }
178 let mut world = World::default();
179 let mut my_system = (|_a: &A, b: &mut B| {
180 let b2 = B { x: 45 };
181 *b = b2;
182 Ok(())
183 })
184 .system();
185 my_system.initialize(&mut world);
186 my_system.run(&world).unwrap();
187 assert_eq!(world.get::<B>().unwrap().x, 45);
188 }
189}