1use crate::{
2 component_container::ComponentContainer,
3 query::ComponentContainerTrait,
4 system::{Borrow, BorrowType, SystemRunState},
5 Component, Ref, RefMut,
6};
7use parking_lot::{
8 MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLockReadGuard, RwLockWriteGuard,
9};
10use std::any::TypeId;
11
12pub trait QueryParameter {
14 type ComponentContainerLock<'a>;
16 type ComponentContainer<'a>: ComponentContainerTrait<'a>;
18
19 fn lock<'a>(state: &SystemRunState<'a>) -> Self::ComponentContainerLock<'a>;
21 fn construct<'a>(
23 lock: &'a mut Self::ComponentContainerLock<'_>,
24 ) -> Self::ComponentContainer<'a>;
25
26 fn get_component_types() -> impl Iterator<Item = Borrow>;
28}
29
30impl<C> QueryParameter for Ref<'_, C>
31where
32 C: Component,
33{
34 type ComponentContainerLock<'a> = Option<MappedRwLockReadGuard<'a, ComponentContainer<C>>>;
35 type ComponentContainer<'a> = Option<&'a ComponentContainer<C>>;
36
37 fn lock<'a>(state: &SystemRunState<'a>) -> Self::ComponentContainerLock<'a> {
38 Some(RwLockReadGuard::map(
39 state
40 .components
41 .get(&TypeId::of::<C>())?
42 .try_read()
43 .expect("the lock should always be available"),
44 |components| components.downcast_ref::<C>(),
45 ))
46 }
47
48 fn construct<'a>(
49 lock: &'a mut Self::ComponentContainerLock<'_>,
50 ) -> Self::ComponentContainer<'a> {
51 Some(lock.as_mut()?)
52 }
53
54 fn get_component_types() -> impl Iterator<Item = Borrow> {
55 std::iter::once(Borrow {
56 id: TypeId::of::<C>(),
57 name: std::any::type_name::<C>(),
58 borrow_type: BorrowType::Immutable,
59 })
60 }
61}
62
63impl<C> QueryParameter for RefMut<'_, C>
64where
65 C: Component,
66{
67 type ComponentContainerLock<'a> = Option<MappedRwLockWriteGuard<'a, ComponentContainer<C>>>;
68 type ComponentContainer<'a> = Option<&'a mut ComponentContainer<C>>;
69
70 fn lock<'a>(state: &SystemRunState<'a>) -> Self::ComponentContainerLock<'a> {
71 Some(RwLockWriteGuard::map(
72 state
73 .components
74 .get(&TypeId::of::<C>())?
75 .try_write()
76 .expect("the lock should always be available"),
77 |components| components.downcast_mut::<C>(),
78 ))
79 }
80
81 fn construct<'a>(
82 lock: &'a mut Self::ComponentContainerLock<'_>,
83 ) -> Self::ComponentContainer<'a> {
84 Some(lock.as_mut()?)
85 }
86
87 fn get_component_types() -> impl Iterator<Item = Borrow> {
88 std::iter::once(Borrow {
89 id: TypeId::of::<C>(),
90 name: std::any::type_name::<C>(),
91 borrow_type: BorrowType::Mutable,
92 })
93 }
94}
95
96pub struct OptionalComponentContainer<T>(pub(crate) T);
97
98impl<P> QueryParameter for Option<P>
99where
100 P: QueryParameter,
101{
102 type ComponentContainerLock<'a> = P::ComponentContainerLock<'a>;
103 type ComponentContainer<'a> = OptionalComponentContainer<P::ComponentContainer<'a>>;
104
105 fn lock<'a>(state: &SystemRunState<'a>) -> Self::ComponentContainerLock<'a> {
106 P::lock(state)
107 }
108
109 fn construct<'a>(
110 lock: &'a mut Self::ComponentContainerLock<'_>,
111 ) -> Self::ComponentContainer<'a> {
112 OptionalComponentContainer(P::construct(lock))
113 }
114
115 fn get_component_types() -> impl Iterator<Item = Borrow> {
116 P::get_component_types()
117 }
118}
119
120macro_rules! query_parameter_tuple {
121 ($($param:ident),*) => {
122 impl<$($param),*> QueryParameter for ($($param,)*)
123 where
124 $($param: QueryParameter,)*
125 {
126 type ComponentContainerLock<'a> = ($($param::ComponentContainerLock<'a>,)*);
127 type ComponentContainer<'a> = ($($param::ComponentContainer<'a>,)*);
128
129 #[allow(clippy::unused_unit)]
130 fn lock<'a>(state: &SystemRunState<'a>) -> Self::ComponentContainerLock<'a> {
131 _ = state;
132 ($($param::lock(state),)*)
133 }
134
135 #[allow(clippy::unused_unit)]
136 fn construct<'this>(state: &'this mut Self::ComponentContainerLock<'_>) -> Self::ComponentContainer<'this> {
137 #[allow(non_snake_case)]
138 let ($($param,)*) = state;
139 ($($param::construct($param),)*)
140 }
141
142 fn get_component_types() -> impl Iterator<Item = Borrow> {
143 std::iter::empty()
144 $(
145 .chain($param::get_component_types())
146 )*
147 }
148 }
149 };
150}
151
152query_parameter_tuple!();
153query_parameter_tuple!(A);
154query_parameter_tuple!(A, B);
155query_parameter_tuple!(A, B, C);
156query_parameter_tuple!(A, B, C, D);
157query_parameter_tuple!(A, B, C, D, E);
158query_parameter_tuple!(A, B, C, D, E, F);
159query_parameter_tuple!(A, B, C, D, E, F, G);
160query_parameter_tuple!(A, B, C, D, E, F, G, H);
161query_parameter_tuple!(A, B, C, D, E, F, G, H, I);
162query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J);
163query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K);
164query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
165query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
166query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
167query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
168query_parameter_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);