ixa/entity/
property_list.rs1use std::any::TypeId;
23
24use seq_macro::seq;
25
26use super::entity::{Entity, EntityId};
27use super::events::PropertyInitializedEvent;
28use super::property::{Property, PropertyInitializationKind};
29use super::property_store::PropertyStore;
30use crate::data_structures::bit_set::BitSet;
31use crate::entity::ContextEntitiesExt;
32use crate::{Context, IxaError};
33
34pub trait PropertyList<E: Entity>: Copy + 'static {
35 fn validate() -> Result<(), IxaError>;
37
38 #[must_use]
40 fn contains_properties(property_type_ids: &[TypeId]) -> bool;
41
42 #[must_use]
44 fn contains_required_properties() -> bool {
45 Self::contains_properties(E::required_property_ids())
46 }
47
48 fn set_values_for_new_entity(
51 &self,
52 entity_id: EntityId<E>,
53 property_store: &mut PropertyStore<E>,
54 );
55
56 #[doc(hidden)]
58 fn emit_initialized_events(
59 &self,
60 context: &mut Context,
61 entity_id: EntityId<E>,
62 subscriptions: &BitSet,
63 );
64
65 #[must_use]
67 fn get_values_for_entity(context: &Context, entity_id: EntityId<E>) -> Self;
68}
69
70pub trait PropertyInitializationList<E: Entity>: PropertyList<E> {}
72
73impl<E: Entity> PropertyList<E> for () {
75 fn validate() -> Result<(), IxaError> {
76 Ok(())
77 }
78 fn contains_properties(property_type_ids: &[TypeId]) -> bool {
79 property_type_ids.is_empty()
80 }
81 fn set_values_for_new_entity(
82 &self,
83 _entity_id: EntityId<E>,
84 _property_store: &mut PropertyStore<E>,
85 ) {
86 }
88
89 fn emit_initialized_events(
90 &self,
91 _context: &mut Context,
92 _entity_id: EntityId<E>,
93 _subscriptions: &BitSet,
94 ) {
95 }
96
97 fn get_values_for_entity(_context: &Context, _entity_id: EntityId<E>) -> Self {}
98}
99
100impl<E: Entity + Copy> PropertyList<E> for E {
103 fn validate() -> Result<(), IxaError> {
104 Ok(())
105 }
106 fn contains_properties(property_type_ids: &[TypeId]) -> bool {
107 property_type_ids.is_empty()
108 }
109 fn set_values_for_new_entity(
110 &self,
111 _entity_id: EntityId<E>,
112 _property_store: &mut PropertyStore<E>,
113 ) {
114 }
116
117 fn emit_initialized_events(
118 &self,
119 _context: &mut Context,
120 _entity_id: EntityId<E>,
121 _subscriptions: &BitSet,
122 ) {
123 }
124
125 fn get_values_for_entity(_context: &Context, _entity_id: EntityId<E>) -> E {
126 E::default()
127 }
128}
129
130impl<E: Entity + Copy> PropertyInitializationList<E> for E {}
131
132fn emit_initialized_event<E, P>(context: &mut Context, entity_id: EntityId<E>, value: P)
133where
134 E: Entity,
135 P: Property<E>,
136{
137 match P::initialization_kind() {
138 PropertyInitializationKind::Derived => {}
139 PropertyInitializationKind::Explicit => {
140 context.emit_event(PropertyInitializedEvent::new(entity_id, value));
141 }
142 PropertyInitializationKind::Constant if value != P::default_const() => {
143 context.emit_event(PropertyInitializedEvent::new(entity_id, value));
144 }
145 PropertyInitializationKind::Constant => {}
146 }
147}
148
149impl<E: Entity, P: Property<E>> PropertyList<E> for (P,) {
170 fn validate() -> Result<(), IxaError> {
171 Ok(())
172 }
173 fn contains_properties(property_type_ids: &[TypeId]) -> bool {
174 property_type_ids.is_empty()
175 || property_type_ids.len() == 1 && property_type_ids[0] == P::type_id()
176 }
177 fn set_values_for_new_entity(
178 &self,
179 entity_id: EntityId<E>,
180 property_store: &mut PropertyStore<E>,
181 ) {
182 let property_value_store = property_store.get_mut::<P>();
183 property_value_store.set(entity_id, self.0);
184 }
185
186 fn emit_initialized_events(
187 &self,
188 context: &mut Context,
189 entity_id: EntityId<E>,
190 subscriptions: &BitSet,
191 ) {
192 if subscriptions.get(P::id()) {
193 emit_initialized_event(context, entity_id, self.0);
194 }
195 }
196
197 fn get_values_for_entity(context: &Context, entity_id: EntityId<E>) -> Self {
198 (context.get_property::<E, P>(entity_id),)
199 }
200}
201
202macro_rules! impl_property_list {
204 ($ct:literal) => {
205 seq!(N in 0..$ct {
206 impl<E: Entity, #( P~N: Property<E>,)*> PropertyList<E> for (#(P~N, )*){
207 fn validate() -> Result<(), IxaError> {
208 let property_type_ids: [TypeId; $ct] = [#(<P~N as $crate::entity::property::Property<E>>::type_id(),)*];
210
211 for i in 0..$ct - 1 {
212 for j in (i + 1)..$ct {
213 if property_type_ids[i] == property_type_ids[j] {
214 return Err(IxaError::DuplicatePropertyInPropertyList {
215 first_index: i,
216 second_index: j,
217 });
218 }
219 }
220 }
221
222 Ok(())
223 }
224
225 fn contains_properties(property_type_ids: &[TypeId]) -> bool {
226 let self_property_type_ids: [TypeId; $ct] = [#(<P~N as $crate::entity::property::Property<E>>::type_id(),)*];
227
228 property_type_ids.len() <= $ct && property_type_ids.iter().all(|id| self_property_type_ids.contains(id))
229 }
230
231 fn set_values_for_new_entity(&self, entity_id: EntityId<E>, property_store: &mut PropertyStore<E>){
232 #({
233 let property_value_store = property_store.get_mut::<P~N>();
234 property_value_store.set(entity_id, self.N);
235 })*
236 }
237
238 fn emit_initialized_events(
239 &self,
240 context: &mut Context,
241 entity_id: EntityId<E>,
242 subscriptions: &BitSet,
243 ) {
244 #(
245 if subscriptions.get(P~N::id()) {
246 emit_initialized_event(context, entity_id, self.N);
247 }
248 )*
249 }
250
251 fn get_values_for_entity(context: &Context, entity_id: EntityId<E>) -> Self {
252 (#(context.get_property::<E, P~N>(entity_id), )*)
253 }
254 }
255 });
256 };
257}
258
259seq!(Z in 2..=20 {
263 impl_property_list!(Z);
264});