1use std::marker::PhantomData;
2
3use paste::paste;
4
5use crate::impl_all;
6
7use super::data_state::DataStateAccessError;
8use super::entity::SystemEntity;
9use super::query::{Query, QueryError};
10use super::systems::{
11 FnNonSendPlaceHolderWithArgs, FnPlaceHolderNonSend, FnPlaceHolderSend,
12 FnSendPlaceHolderWithArgs, IntoNonSendSystem, IntoSendSystem, QuerySystem, System, SystemError,
13};
14
15macro_rules! impl_queries {
16 ($($t:tt)*) => {
17 impl<Queryable, $($t:Query<Queryable>),*> Query<Queryable> for ($($t,)*) {
18 #[allow(non_snake_case)]
19 fn query(q: &mut Queryable, e: &SystemEntity) -> Result<Self,DataStateAccessError> {
20 let ($($t,)*) =($($t::query(q,e),)*);
21 match($($t,)*) {
22 ($(Ok($t),)*) => { Ok(($($t,)*)) },
23 ($($t,)*) => {
24 $(if let Ok($t) = $t {<$t>::consume($t,q,e)?;})*;
25 Err(DataStateAccessError::NotAvailableError)
26 }
27 }
28 }
29 fn consume(self, q: &mut Queryable, e: &SystemEntity) -> Result<(), DataStateAccessError> {
30 #[allow(non_snake_case)]
31 let ($($t,)*) = self;
32 $($t::consume($t, q, e)?;)*
33 Ok(())
34 }
35 }
36 };
37}
38
39impl_all!(impl_queries);
40
41macro_rules! impl_systems {
42 ($($t:tt)*) => {
43 paste!{
44 pub struct [<QuerySystemFn $($t)*>]<$($t:Query<Queryable>),*, Queryable, Fn: FnMut($(&mut $t),*)>(
45 Fn,
46 PhantomData<($($t,)* Queryable)>,
47 );
48
49 pub struct [<QuerySystemFnWithArgs $($t)*>]<
50 $($t:Query<Queryable>,)*
51 Queryable,
52 EngineArgs,
53 Fn: FnMut(&EngineArgs, $(&mut $t,)*),
54 >(Fn, PhantomData<($($t,)* Queryable, EngineArgs)>);
55
56 impl<$($t:Query<Queryable>,)* Queryable, EngineArgs, Fn: FnMut(&EngineArgs, $(&mut $t,)*)>
57 [<QuerySystemFnWithArgs $($t)*>]<$($t,)* Queryable, EngineArgs, Fn>
58 {
59 pub fn new(f: Fn) -> Self {
60 Self(f, PhantomData)
61 }
62 }
63
64 impl<$($t:Query<Queryable>),*, Queryable, Fn: FnMut($(&mut $t,)*)> [<QuerySystemFn $($t)*>]<$($t,)* Queryable, Fn> {
65 pub fn new(f: Fn) -> Self {
66 Self(f, PhantomData)
67 }
68 }
69
70 impl<$($t:Query<Queryable>,)* Queryable, Fn: FnMut($(&mut $t,)*), EngineArgs>
71 QuerySystem<Queryable, EngineArgs> for [<QuerySystemFn $($t)*>]<$($t,)* Queryable, Fn>
72 {
73 type Query = ($($t,)*);
74
75 fn run(&mut self, _engine_args: &EngineArgs, args: &mut Self::Query) {
76 #[allow(non_snake_case)]
77 let ($($t,)*) = args;
78 (self.0)($($t,)*);
79 }
80 }
81
82 impl<$($t:Query<Queryable>,)* Queryable, Fn: FnMut(&EngineArgs, $(&mut $t,)*), EngineArgs>
83 QuerySystem<Queryable, EngineArgs>
84 for [<QuerySystemFnWithArgs $($t)*>]<$($t,)* Queryable, EngineArgs, Fn>
85 {
86 type Query = ($($t,)*);
87
88 fn run(&mut self, engine_args: &EngineArgs, args: &mut Self::Query) {
89 #[allow(non_snake_case)]
90 let ($($t,)*) = args;
91 (self.0)(engine_args, $($t,)*);
92 }
93 }
94
95 pub struct [<QuerySystemWrapper $($t)*>]<
96 $($t:Query<Queryable>,)*
97 Queryable,
98 EngineArgs,
99 QS: QuerySystem<Queryable, EngineArgs, Query = ($($t,)*)>,
100 > {
101 system: QS,
102 args: Option<($($t,)*)>,
103 marker: PhantomData<(Queryable, EngineArgs)>,
104 }
105
106 impl<
107 $($t:Query<Queryable>,)*
108 Queryable,
109 EngineArgs,
110 QS: QuerySystem<Queryable, EngineArgs, Query = ($($t,)*)>,
111 > [<QuerySystemWrapper $($t)*>]<$($t,)* Queryable, EngineArgs, QS>
112 {
113 pub fn new(system: QS) -> Self {
114 Self {
115 system,
116 args: None,
117 marker: PhantomData,
118 }
119 }
120 }
121 impl<
122 $($t:Query<Queryable>,)*
123 Queryable,
124 EngineArgs,
125 QS: QuerySystem<Queryable, EngineArgs, Query = ($($t,)*)>,
126 > System<Queryable, EngineArgs> for [<QuerySystemWrapper $($t)*>]<$($t,)* Queryable, EngineArgs, QS>
127 {
128 fn prepare_args(
129 &mut self,
130 queryable: &mut Queryable,
131 system_id: &SystemEntity,
132 ) -> Result<(), QueryError> {
133 assert!(self.args.is_none());
134 self.args = Some(<($($t,)*)>::query(queryable, system_id).map_err(|_|QueryError::NotAvailable)?);
135 Ok(())
136 }
137
138 fn run(&mut self, engine_args: &EngineArgs) -> Result<(), SystemError> {
139 let args = self.args.as_mut();
140 if let Some(args) = args {
141 self.system.run(engine_args, args);
142 Ok(())
143 } else {
144 Err(SystemError::MissingArgs)
145 }
146 }
147
148 fn consume(
149 &mut self,
150 queryable: &mut Queryable,
151 system_id: &SystemEntity,
152 ) -> Result<(), DataStateAccessError> {
153 self.args.take().unwrap().consume(queryable, system_id)
154 }
155 }
156
157
158
159 impl<$($t:Query<Queryable>,)* Queryable, EngineArgs, Fn: FnMut($(&mut $t,)*)>
160 IntoNonSendSystem<Queryable, EngineArgs, FnPlaceHolderNonSend<($($t,)*), Queryable>> for Fn
161 {
162 fn into_system(self) -> impl System<Queryable, EngineArgs> {
163 [<QuerySystemWrapper $($t)*>]::new([<QuerySystemFn $($t)*>]::new(self))
164 }
165 }
166 impl<
167 $($t:Query<Queryable>+Send,)*
168 Queryable: Send,
169 EngineArgs: Send,
170 Fn: FnMut($(&mut $t,)*) + Send,
171 > IntoSendSystem<Queryable, EngineArgs, FnPlaceHolderSend<($($t,)*), Queryable>> for Fn
172 {
173 fn into_system(self) -> impl System<Queryable, EngineArgs> + Send {
174 [<QuerySystemWrapper $($t)*>]::new([<QuerySystemFn $($t)*>]::new(self))
175 }
176 }
177 impl<
178 $($t:Query<Queryable>+Send,)*
179 Queryable: Send,
180 EngineArgs: Send,
181 Fn: FnMut(&EngineArgs,$(&mut $t,)*) + Send,
182 > IntoSendSystem<Queryable, EngineArgs, FnSendPlaceHolderWithArgs<($($t,)*), Queryable>> for Fn
183 {
184 fn into_system(self) -> impl System<Queryable, EngineArgs> + Send {
185 [<QuerySystemWrapper $($t)*>]::new([<QuerySystemFnWithArgs $($t)*>]::new(self))
186 }
187 }
188
189
190 impl<$($t:Query<Queryable>,)* Queryable, EngineArgs, Fn: FnMut(&EngineArgs, $(&mut $t,)*)>
191 IntoNonSendSystem<Queryable, EngineArgs, FnNonSendPlaceHolderWithArgs<($($t,)*), Queryable>>
192 for Fn
193 {
194 fn into_system(self) -> impl System<Queryable, EngineArgs> {
195 [<QuerySystemWrapper $($t)*>]::new([<QuerySystemFnWithArgs $($t)*>]::new(self))
196 }
197
198 }
199 }
200 };
201}
202
203impl_all!(impl_systems);
205#[cfg(test)]
206mod tests {
207 use crate::engine::{
208 query::{ReadC, WriteC},
209 scene::DummySceneRegistry,
210 systems::{BoxedSendSystem, IntoNonSendSystem},
211 };
212
213 #[test]
214 fn complex_queries() {
215 let reg = <DummySceneRegistry>::new();
216 let mut reg = reg.registry;
217
218 let mut sys1 = BoxedSendSystem::from_system(
219 (|_args: &mut (), _readc: &mut ReadC<()>, _write_i: &mut WriteC<i32>| {}).into_system(),
220 );
221 let mut sys2 = BoxedSendSystem::from_system(
222 (|_args: &mut (), _data: &mut (ReadC<()>, WriteC<i16>)| {}).into_system(),
223 );
224 let mut sys3 = BoxedSendSystem::from_system(
225 (|_args: &mut (), _data: &mut (ReadC<()>, WriteC<i32>)| {}).into_system(),
226 );
227 sys1.prepare_args(&mut reg).unwrap();
228 sys1.run(&()).unwrap();
229
230 sys2.prepare_args(&mut reg).unwrap();
231 sys2.run(&()).unwrap();
232
233 sys3.prepare_args(&mut reg).unwrap_err();
234
235 sys1.consume(&mut reg).unwrap();
236 sys2.consume(&mut reg).unwrap();
237
238 sys3.prepare_args(&mut reg).unwrap();
239 sys3.run(&()).unwrap();
240 sys3.consume(&mut reg).unwrap();
241 }
242}