Skip to main content

matrix_engine/engine/
group_query.rs

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
203// impl_systems!(A B C);
204impl_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}