1use alloc::vec::Vec;
7use core::any::TypeId;
8
9use crate::component::ComponentId;
10use crate::query::ExactIdPolicy;
11use crate::EntityId;
12
13#[derive(Clone, Debug, Default)]
15pub struct QuerySpec {
16 pub(crate) required: Vec<TypeId>,
17 pub(crate) required_ids: Vec<ComponentId>,
18 pub(crate) without: Vec<TypeId>,
19 pub(crate) without_ids: Vec<ComponentId>,
20 pub(crate) with_tags: Vec<TypeId>,
21 pub(crate) with_tag_ids: Vec<ComponentId>,
22 pub(crate) without_tags: Vec<TypeId>,
23 pub(crate) without_tag_ids: Vec<ComponentId>,
24 pub(crate) added: Vec<TypeId>,
25 pub(crate) added_ids: Vec<ComponentId>,
26 pub(crate) changed: Vec<TypeId>,
27 pub(crate) changed_ids: Vec<ComponentId>,
28 pub(crate) exact_ids: Option<Vec<EntityId>>,
29 pub(crate) exact_id_policy: Option<ExactIdPolicy>,
30}
31
32impl QuerySpec {
33 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn with<T: 'static>(mut self) -> Self {
40 self.required.push(TypeId::of::<T>());
41 self
42 }
43
44 pub fn with_id(mut self, id: ComponentId) -> Self {
46 self.required_ids.push(id);
47 self
48 }
49
50 pub fn without<T: 'static>(mut self) -> Self {
52 self.without.push(TypeId::of::<T>());
53 self
54 }
55
56 pub fn without_id(mut self, id: ComponentId) -> Self {
58 self.without_ids.push(id);
59 self
60 }
61
62 pub fn with_tag<T: 'static>(mut self) -> Self {
64 self.with_tags.push(TypeId::of::<T>());
65 self
66 }
67
68 pub fn with_tag_id(mut self, id: ComponentId) -> Self {
70 self.with_tag_ids.push(id);
71 self
72 }
73
74 pub fn without_tag<T: 'static>(mut self) -> Self {
76 self.without_tags.push(TypeId::of::<T>());
77 self
78 }
79
80 pub fn without_tag_id(mut self, id: ComponentId) -> Self {
82 self.without_tag_ids.push(id);
83 self
84 }
85
86 pub fn added<T: 'static>(mut self) -> Self {
88 self.added.push(TypeId::of::<T>());
89 self
90 }
91
92 pub fn added_id(mut self, id: ComponentId) -> Self {
94 self.added_ids.push(id);
95 self
96 }
97
98 pub fn changed<T: 'static>(mut self) -> Self {
100 self.changed.push(TypeId::of::<T>());
101 self
102 }
103
104 pub fn changed_id(mut self, id: ComponentId) -> Self {
106 self.changed_ids.push(id);
107 self
108 }
109
110 pub fn exact_ids(mut self, ids: Vec<EntityId>, policy: ExactIdPolicy) -> Self {
112 self.exact_ids = Some(ids);
113 self.exact_id_policy = Some(policy);
114 self
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use crate::component::ComponentOptions;
122 use crate::world::WorldBuilder;
123
124 #[derive(Clone, Copy)]
125 struct Position;
126
127 #[derive(Clone, Copy)]
128 struct Player;
129
130 #[test]
131 fn dynamic_id_builders_populate_each_selector_group() {
132 let mut builder = WorldBuilder::new();
133 let position = builder
134 .register_component::<Position>(ComponentOptions::sparse())
135 .expect("position");
136 let player = builder
137 .register_component::<Player>(ComponentOptions::tag())
138 .expect("player");
139
140 let spec = QuerySpec::new()
141 .with_id(position.clone())
142 .without_id(position.clone())
143 .with_tag_id(player.clone())
144 .without_tag_id(player)
145 .added_id(position.clone())
146 .changed_id(position);
147
148 assert_eq!(spec.required_ids.len(), 1);
149 assert_eq!(spec.without_ids.len(), 1);
150 assert_eq!(spec.with_tag_ids.len(), 1);
151 assert_eq!(spec.without_tag_ids.len(), 1);
152 assert_eq!(spec.added_ids.len(), 1);
153 assert_eq!(spec.changed_ids.len(), 1);
154 }
155}