1use std::collections::BTreeSet;
45use std::fmt;
46
47use crate::ecs::archetype::Archetype;
48use crate::ecs::component::ComponentId;
49use crate::ecs::entity::Entity;
50use crate::ecs::resource::{NonSendResourceId, ResourceId};
51use crate::ecs::World;
52
53pub trait WorldQuery {
114 type Item<'w>;
125
126 type State: QueryState;
136
137 fn init_state(world: &World) -> Self::State;
150
151 fn component_access(state: &Self::State) -> BTreeSet<ComponentId>;
164
165 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool;
179
180 fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>>;
201
202 fn fetch_mut<'w>(
218 state: &Self::State,
219 world: &'w mut World,
220 entity: Entity,
221 ) -> Option<Self::Item<'w>> {
222 Self::fetch(state, world, entity)
224 }
225}
226
227pub trait ReadOnlyWorldQuery: WorldQuery {}
264
265pub trait QueryState: Send + Sync + Clone + 'static {}
291
292impl<T: Send + Sync + Clone + 'static> QueryState for T {}
294
295impl WorldQuery for Entity {
304 type Item<'w> = Entity;
305 type State = ();
306
307 #[inline]
308 fn init_state(_world: &World) -> Self::State {
309 }
311
312 #[inline]
313 fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
314 BTreeSet::new()
316 }
317
318 #[inline]
319 fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool {
320 true
322 }
323
324 #[inline]
325 fn fetch<'w>(_state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
326 if world.is_alive(entity) {
328 Some(entity)
329 } else {
330 None
331 }
332 }
333}
334
335impl ReadOnlyWorldQuery for Entity {}
336
337impl WorldQuery for () {
346 type Item<'w> = ();
347 type State = ();
348
349 #[inline]
350 fn init_state(_world: &World) -> Self::State {}
351
352 #[inline]
353 fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
354 BTreeSet::new()
355 }
356
357 #[inline]
358 fn matches_archetype(_state: &Self::State, _archetype: &Archetype) -> bool {
359 true
360 }
361
362 #[inline]
363 fn fetch<'w>(
364 _state: &Self::State,
365 _world: &'w World,
366 _entity: Entity,
367 ) -> Option<Self::Item<'w>> {
368 Some(())
369 }
370}
371
372impl ReadOnlyWorldQuery for () {}
373
374macro_rules! impl_tuple_world_query {
380 ($($T:ident),*) => {
381 #[allow(non_snake_case)]
382 impl<$($T: WorldQuery),*> WorldQuery for ($($T,)*) {
383 type Item<'w> = ($($T::Item<'w>,)*);
384 type State = ($($T::State,)*);
385
386 #[inline]
387 fn init_state(world: &World) -> Self::State {
388 ($($T::init_state(world),)*)
389 }
390
391 #[inline]
392 fn component_access(state: &Self::State) -> BTreeSet<ComponentId> {
393 let ($($T,)*) = state;
394 let mut access = BTreeSet::new();
395 $(
396 access.extend($T::component_access($T));
397 )*
398 access
399 }
400
401 #[inline]
402 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
403 let ($($T,)*) = state;
404 true $(&& $T::matches_archetype($T, archetype))*
405 }
406
407 #[inline]
408 fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
409 let ($($T,)*) = state;
410 Some((
411 $($T::fetch($T, world, entity)?,)*
412 ))
413 }
414 }
415
416 impl<$($T: ReadOnlyWorldQuery),*> ReadOnlyWorldQuery for ($($T,)*) {}
418 };
419}
420
421impl_tuple_world_query!(A);
423impl_tuple_world_query!(A, B);
424impl_tuple_world_query!(A, B, C);
425impl_tuple_world_query!(A, B, C, D);
426impl_tuple_world_query!(A, B, C, D, E);
427impl_tuple_world_query!(A, B, C, D, E, F);
428impl_tuple_world_query!(A, B, C, D, E, F, G);
429impl_tuple_world_query!(A, B, C, D, E, F, G, H);
430
431#[derive(Debug, Clone, Copy, Default)]
459pub struct With<T>(std::marker::PhantomData<T>);
460
461impl<T> With<T> {
462 #[inline]
464 pub fn new() -> Self {
465 Self(std::marker::PhantomData)
466 }
467}
468
469impl<T: crate::ecs::Component> WorldQuery for With<T> {
470 type Item<'w> = ();
471 type State = ComponentId;
472
473 #[inline]
474 fn init_state(_world: &World) -> Self::State {
475 ComponentId::of::<T>()
476 }
477
478 #[inline]
479 fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
480 BTreeSet::new()
482 }
483
484 #[inline]
485 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
486 archetype.has_component(*state)
487 }
488
489 #[inline]
490 fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
491 if world.has::<T>(entity) {
493 Some(())
494 } else {
495 let _ = state;
497 None
498 }
499 }
500}
501
502impl<T: crate::ecs::Component> ReadOnlyWorldQuery for With<T> {}
503
504#[derive(Debug, Clone, Copy, Default)]
524pub struct Without<T>(std::marker::PhantomData<T>);
525
526impl<T> Without<T> {
527 #[inline]
529 pub fn new() -> Self {
530 Self(std::marker::PhantomData)
531 }
532}
533
534impl<T: crate::ecs::Component> WorldQuery for Without<T> {
535 type Item<'w> = ();
536 type State = ComponentId;
537
538 #[inline]
539 fn init_state(_world: &World) -> Self::State {
540 ComponentId::of::<T>()
541 }
542
543 #[inline]
544 fn component_access(_state: &Self::State) -> BTreeSet<ComponentId> {
545 BTreeSet::new()
546 }
547
548 #[inline]
549 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
550 !archetype.has_component(*state)
551 }
552
553 #[inline]
554 fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
555 if !world.has::<T>(entity) {
557 Some(())
558 } else {
559 let _ = state;
560 None
561 }
562 }
563}
564
565impl<T: crate::ecs::Component> ReadOnlyWorldQuery for Without<T> {}
566
567impl<T: crate::ecs::Component> WorldQuery for &T {
616 type Item<'w> = &'w T;
617 type State = ComponentId;
618
619 #[inline]
620 fn init_state(_world: &World) -> Self::State {
621 ComponentId::of::<T>()
622 }
623
624 #[inline]
625 fn component_access(state: &Self::State) -> BTreeSet<ComponentId> {
626 let mut set = BTreeSet::new();
627 set.insert(*state);
628 set
629 }
630
631 #[inline]
632 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
633 archetype.has_component(*state)
634 }
635
636 #[inline]
637 fn fetch<'w>(state: &Self::State, world: &'w World, entity: Entity) -> Option<Self::Item<'w>> {
638 let _ = state;
640
641 world.get::<T>(entity)
643 }
644}
645
646impl<T: crate::ecs::Component> ReadOnlyWorldQuery for &T {}
647
648#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
658pub struct WriteAccess(pub ComponentId);
659
660#[derive(Debug, Clone, Copy, PartialEq, Eq)]
665pub struct MutState {
666 pub component_id: ComponentId,
668}
669
670impl MutState {
671 #[inline]
673 pub fn of<T: crate::ecs::Component>() -> Self {
674 Self {
675 component_id: ComponentId::of::<T>(),
676 }
677 }
678}
679
680impl<T: crate::ecs::Component> WorldQuery for &mut T {
741 type Item<'w> = &'w mut T;
742 type State = MutState;
743
744 #[inline]
745 fn init_state(_world: &World) -> Self::State {
746 MutState::of::<T>()
747 }
748
749 #[inline]
750 fn component_access(state: &Self::State) -> BTreeSet<ComponentId> {
751 let mut set = BTreeSet::new();
752 set.insert(state.component_id);
753 set
754 }
755
756 #[inline]
757 fn matches_archetype(state: &Self::State, archetype: &Archetype) -> bool {
758 archetype.has_component(state.component_id)
759 }
760
761 #[inline]
766 fn fetch<'w>(
767 _state: &Self::State,
768 _world: &'w World,
769 _entity: Entity,
770 ) -> Option<Self::Item<'w>> {
771 None
774 }
775
776 #[inline]
777 fn fetch_mut<'w>(
778 state: &Self::State,
779 world: &'w mut World,
780 entity: Entity,
781 ) -> Option<Self::Item<'w>> {
782 let _ = state;
784
785 world.get_mut::<T>(entity)
787 }
788}
789
790#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
802pub enum AccessType {
803 Read,
805 Write,
807}
808
809#[derive(Debug, Clone, Default)]
813pub struct Access {
814 reads: BTreeSet<ComponentId>,
816 writes: BTreeSet<ComponentId>,
818 resource_reads: BTreeSet<ResourceId>,
820 resource_writes: BTreeSet<ResourceId>,
822 non_send_reads: BTreeSet<NonSendResourceId>,
824 non_send_writes: BTreeSet<NonSendResourceId>,
826}
827
828impl Access {
829 #[inline]
831 pub fn new() -> Self {
832 Self::default()
833 }
834
835 #[inline]
837 pub fn add_read(&mut self, id: ComponentId) {
838 self.reads.insert(id);
839 }
840
841 #[inline]
845 pub fn add_write(&mut self, id: ComponentId) {
846 self.writes.insert(id);
847 }
848
849 #[inline]
851 pub fn reads(&self) -> impl Iterator<Item = &ComponentId> {
852 self.reads.iter().chain(self.writes.iter())
853 }
854
855 #[inline]
857 pub fn writes(&self) -> &BTreeSet<ComponentId> {
858 &self.writes
859 }
860
861 #[inline]
863 pub fn reads_only(&self) -> impl Iterator<Item = &ComponentId> {
864 self.reads.iter().filter(|id| !self.writes.contains(id))
865 }
866
867 #[inline]
873 pub fn conflicts_with(&self, other: &Access) -> bool {
874 for write in &self.writes {
878 if other.reads.contains(write) || other.writes.contains(write) {
879 return true;
880 }
881 }
882
883 for write in &other.writes {
885 if self.reads.contains(write) {
886 return true;
887 }
888 }
889
890 if self.resource_conflicts_with(other) {
892 return true;
893 }
894
895 self.non_send_conflicts_with(other)
897 }
898
899 #[inline]
903 pub fn is_read_only(&self) -> bool {
904 self.writes.is_empty() && self.resource_writes.is_empty() && self.non_send_writes.is_empty()
905 }
906
907 #[inline]
909 pub fn extend(&mut self, other: &Access) {
910 self.reads.extend(other.reads.iter().copied());
911 self.writes.extend(other.writes.iter().copied());
912 self.resource_reads
913 .extend(other.resource_reads.iter().copied());
914 self.resource_writes
915 .extend(other.resource_writes.iter().copied());
916 self.non_send_reads
917 .extend(other.non_send_reads.iter().copied());
918 self.non_send_writes
919 .extend(other.non_send_writes.iter().copied());
920 }
921
922 #[inline]
928 pub fn add_resource_read(&mut self, id: ResourceId) {
929 self.resource_reads.insert(id);
930 }
931
932 #[inline]
936 pub fn add_resource_write(&mut self, id: ResourceId) {
937 self.resource_writes.insert(id);
938 }
939
940 #[inline]
942 pub fn resource_reads(&self) -> impl Iterator<Item = &ResourceId> {
943 self.resource_reads
944 .iter()
945 .chain(self.resource_writes.iter())
946 }
947
948 #[inline]
950 pub fn resource_writes(&self) -> &BTreeSet<ResourceId> {
951 &self.resource_writes
952 }
953
954 #[inline]
956 pub fn resource_reads_only(&self) -> impl Iterator<Item = &ResourceId> {
957 self.resource_reads
958 .iter()
959 .filter(|id| !self.resource_writes.contains(id))
960 }
961
962 #[inline]
967 pub fn resource_conflicts_with(&self, other: &Access) -> bool {
968 for write in &self.resource_writes {
970 if other.resource_reads.contains(write) || other.resource_writes.contains(write) {
971 return true;
972 }
973 }
974
975 for write in &other.resource_writes {
977 if self.resource_reads.contains(write) {
978 return true;
979 }
980 }
981
982 false
983 }
984
985 #[inline]
987 pub fn has_resource_access(&self) -> bool {
988 !self.resource_reads.is_empty() || !self.resource_writes.is_empty()
989 }
990
991 #[inline]
993 pub fn has_component_access(&self) -> bool {
994 !self.reads.is_empty() || !self.writes.is_empty()
995 }
996
997 #[inline]
1003 pub fn add_non_send_read(&mut self, id: NonSendResourceId) {
1004 self.non_send_reads.insert(id);
1005 }
1006
1007 #[inline]
1011 pub fn add_non_send_write(&mut self, id: NonSendResourceId) {
1012 self.non_send_writes.insert(id);
1013 }
1014
1015 #[inline]
1017 pub fn non_send_reads(&self) -> impl Iterator<Item = &NonSendResourceId> {
1018 self.non_send_reads
1019 .iter()
1020 .chain(self.non_send_writes.iter())
1021 }
1022
1023 #[inline]
1025 pub fn non_send_writes(&self) -> &BTreeSet<NonSendResourceId> {
1026 &self.non_send_writes
1027 }
1028
1029 #[inline]
1031 pub fn non_send_reads_only(&self) -> impl Iterator<Item = &NonSendResourceId> {
1032 self.non_send_reads
1033 .iter()
1034 .filter(|id| !self.non_send_writes.contains(id))
1035 }
1036
1037 #[inline]
1042 pub fn non_send_conflicts_with(&self, other: &Access) -> bool {
1043 for write in &self.non_send_writes {
1045 if other.non_send_reads.contains(write) || other.non_send_writes.contains(write) {
1046 return true;
1047 }
1048 }
1049
1050 for write in &other.non_send_writes {
1052 if self.non_send_reads.contains(write) {
1053 return true;
1054 }
1055 }
1056
1057 false
1058 }
1059
1060 #[inline]
1062 pub fn has_non_send_access(&self) -> bool {
1063 !self.non_send_reads.is_empty() || !self.non_send_writes.is_empty()
1064 }
1065
1066 #[inline]
1070 pub fn requires_main_thread(&self) -> bool {
1071 self.has_non_send_access()
1072 }
1073
1074 pub fn get_conflicts(&self, other: &Access) -> Option<AccessConflict> {
1110 let mut component_conflicts = Vec::new();
1111 let mut resource_conflicts = Vec::new();
1112 let mut non_send_conflicts = Vec::new();
1113
1114 for &write in &self.writes {
1116 if other.reads.contains(&write) {
1117 component_conflicts.push(ConflictInfo::new(
1118 write,
1119 AccessType::Write,
1120 AccessType::Read,
1121 ));
1122 } else if other.writes.contains(&write) {
1123 component_conflicts.push(ConflictInfo::new(
1124 write,
1125 AccessType::Write,
1126 AccessType::Write,
1127 ));
1128 }
1129 }
1130
1131 for &write in &other.writes {
1133 if self.reads.contains(&write) && !self.writes.contains(&write) {
1134 component_conflicts.push(ConflictInfo::new(
1136 write,
1137 AccessType::Read,
1138 AccessType::Write,
1139 ));
1140 }
1141 }
1142
1143 for &write in &self.resource_writes {
1145 if other.resource_reads.contains(&write) {
1146 resource_conflicts.push(ResourceConflictInfo::new(
1147 write,
1148 AccessType::Write,
1149 AccessType::Read,
1150 ));
1151 } else if other.resource_writes.contains(&write) {
1152 resource_conflicts.push(ResourceConflictInfo::new(
1153 write,
1154 AccessType::Write,
1155 AccessType::Write,
1156 ));
1157 }
1158 }
1159
1160 for &write in &other.resource_writes {
1162 if self.resource_reads.contains(&write) && !self.resource_writes.contains(&write) {
1163 resource_conflicts.push(ResourceConflictInfo::new(
1164 write,
1165 AccessType::Read,
1166 AccessType::Write,
1167 ));
1168 }
1169 }
1170
1171 for &write in &self.non_send_writes {
1173 if other.non_send_reads.contains(&write) {
1174 non_send_conflicts.push(NonSendConflictInfo::new(
1175 write,
1176 AccessType::Write,
1177 AccessType::Read,
1178 ));
1179 } else if other.non_send_writes.contains(&write) {
1180 non_send_conflicts.push(NonSendConflictInfo::new(
1181 write,
1182 AccessType::Write,
1183 AccessType::Write,
1184 ));
1185 }
1186 }
1187
1188 for &write in &other.non_send_writes {
1190 if self.non_send_reads.contains(&write) && !self.non_send_writes.contains(&write) {
1191 non_send_conflicts.push(NonSendConflictInfo::new(
1192 write,
1193 AccessType::Read,
1194 AccessType::Write,
1195 ));
1196 }
1197 }
1198
1199 if component_conflicts.is_empty()
1200 && resource_conflicts.is_empty()
1201 && non_send_conflicts.is_empty()
1202 {
1203 None
1204 } else {
1205 Some(AccessConflict {
1206 component_conflicts,
1207 resource_conflicts,
1208 non_send_conflicts,
1209 })
1210 }
1211 }
1212
1213 #[inline]
1215 pub fn is_empty(&self) -> bool {
1216 self.reads.is_empty()
1217 && self.writes.is_empty()
1218 && self.resource_reads.is_empty()
1219 && self.resource_writes.is_empty()
1220 && self.non_send_reads.is_empty()
1221 && self.non_send_writes.is_empty()
1222 }
1223
1224 #[inline]
1226 pub fn clear(&mut self) {
1227 self.reads.clear();
1228 self.writes.clear();
1229 self.resource_reads.clear();
1230 self.resource_writes.clear();
1231 self.non_send_reads.clear();
1232 self.non_send_writes.clear();
1233 }
1234}
1235
1236#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1244pub struct ConflictInfo {
1245 pub component_id: ComponentId,
1247 pub first_access: AccessType,
1249 pub second_access: AccessType,
1251}
1252
1253impl ConflictInfo {
1254 #[inline]
1256 pub fn new(
1257 component_id: ComponentId,
1258 first_access: AccessType,
1259 second_access: AccessType,
1260 ) -> Self {
1261 Self {
1262 component_id,
1263 first_access,
1264 second_access,
1265 }
1266 }
1267
1268 #[inline]
1270 pub fn is_write_write(&self) -> bool {
1271 self.first_access == AccessType::Write && self.second_access == AccessType::Write
1272 }
1273
1274 #[inline]
1276 pub fn is_read_write(&self) -> bool {
1277 (self.first_access == AccessType::Read && self.second_access == AccessType::Write)
1278 || (self.first_access == AccessType::Write && self.second_access == AccessType::Read)
1279 }
1280}
1281
1282impl fmt::Display for ConflictInfo {
1283 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1284 write!(
1285 f,
1286 "Component {:?}: {:?} vs {:?}",
1287 self.component_id, self.first_access, self.second_access
1288 )
1289 }
1290}
1291
1292#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1294pub struct ResourceConflictInfo {
1295 pub resource_id: ResourceId,
1297 pub first_access: AccessType,
1299 pub second_access: AccessType,
1301}
1302
1303impl ResourceConflictInfo {
1304 #[inline]
1306 pub fn new(
1307 resource_id: ResourceId,
1308 first_access: AccessType,
1309 second_access: AccessType,
1310 ) -> Self {
1311 Self {
1312 resource_id,
1313 first_access,
1314 second_access,
1315 }
1316 }
1317
1318 #[inline]
1320 pub fn is_write_write(&self) -> bool {
1321 self.first_access == AccessType::Write && self.second_access == AccessType::Write
1322 }
1323}
1324
1325impl fmt::Display for ResourceConflictInfo {
1326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1327 write!(
1328 f,
1329 "Resource {:?}: {:?} vs {:?}",
1330 self.resource_id, self.first_access, self.second_access
1331 )
1332 }
1333}
1334
1335#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1337pub struct NonSendConflictInfo {
1338 pub resource_id: NonSendResourceId,
1340 pub first_access: AccessType,
1342 pub second_access: AccessType,
1344}
1345
1346impl NonSendConflictInfo {
1347 #[inline]
1349 pub fn new(
1350 resource_id: NonSendResourceId,
1351 first_access: AccessType,
1352 second_access: AccessType,
1353 ) -> Self {
1354 Self {
1355 resource_id,
1356 first_access,
1357 second_access,
1358 }
1359 }
1360
1361 #[inline]
1363 pub fn is_write_write(&self) -> bool {
1364 self.first_access == AccessType::Write && self.second_access == AccessType::Write
1365 }
1366}
1367
1368impl fmt::Display for NonSendConflictInfo {
1369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1370 write!(
1371 f,
1372 "NonSendResource {:?}: {:?} vs {:?}",
1373 self.resource_id, self.first_access, self.second_access
1374 )
1375 }
1376}
1377
1378#[derive(Debug, Clone, PartialEq, Eq)]
1409pub struct AccessConflict {
1410 component_conflicts: Vec<ConflictInfo>,
1412 resource_conflicts: Vec<ResourceConflictInfo>,
1414 non_send_conflicts: Vec<NonSendConflictInfo>,
1416}
1417
1418impl AccessConflict {
1419 #[inline]
1421 pub fn new() -> Self {
1422 Self {
1423 component_conflicts: Vec::new(),
1424 resource_conflicts: Vec::new(),
1425 non_send_conflicts: Vec::new(),
1426 }
1427 }
1428
1429 #[inline]
1431 pub fn component_conflicts(&self) -> &[ConflictInfo] {
1432 &self.component_conflicts
1433 }
1434
1435 #[inline]
1437 pub fn resource_conflicts(&self) -> &[ResourceConflictInfo] {
1438 &self.resource_conflicts
1439 }
1440
1441 #[inline]
1443 pub fn non_send_conflicts(&self) -> &[NonSendConflictInfo] {
1444 &self.non_send_conflicts
1445 }
1446
1447 #[inline]
1449 pub fn component_count(&self) -> usize {
1450 self.component_conflicts.len()
1451 }
1452
1453 #[inline]
1455 pub fn resource_count(&self) -> usize {
1456 self.resource_conflicts.len()
1457 }
1458
1459 #[inline]
1461 pub fn non_send_count(&self) -> usize {
1462 self.non_send_conflicts.len()
1463 }
1464
1465 #[inline]
1467 pub fn total_count(&self) -> usize {
1468 self.component_conflicts.len()
1469 + self.resource_conflicts.len()
1470 + self.non_send_conflicts.len()
1471 }
1472
1473 #[inline]
1475 pub fn is_empty(&self) -> bool {
1476 self.component_conflicts.is_empty()
1477 && self.resource_conflicts.is_empty()
1478 && self.non_send_conflicts.is_empty()
1479 }
1480
1481 #[inline]
1483 pub fn has_write_write(&self) -> bool {
1484 self.component_conflicts.iter().any(|c| c.is_write_write())
1485 || self.resource_conflicts.iter().any(|c| c.is_write_write())
1486 || self.non_send_conflicts.iter().any(|c| c.is_write_write())
1487 }
1488
1489 #[inline]
1491 pub fn conflicting_components(&self) -> impl Iterator<Item = ComponentId> + '_ {
1492 self.component_conflicts.iter().map(|c| c.component_id)
1493 }
1494
1495 #[inline]
1497 pub fn conflicting_resources(&self) -> impl Iterator<Item = ResourceId> + '_ {
1498 self.resource_conflicts.iter().map(|c| c.resource_id)
1499 }
1500
1501 #[inline]
1503 pub fn conflicting_non_send_resources(&self) -> impl Iterator<Item = NonSendResourceId> + '_ {
1504 self.non_send_conflicts.iter().map(|c| c.resource_id)
1505 }
1506}
1507
1508impl Default for AccessConflict {
1509 fn default() -> Self {
1510 Self::new()
1511 }
1512}
1513
1514impl fmt::Display for AccessConflict {
1515 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1516 write!(f, "AccessConflict(")?;
1517 let mut first = true;
1518
1519 for conflict in &self.component_conflicts {
1520 if !first {
1521 write!(f, ", ")?;
1522 }
1523 write!(f, "{}", conflict)?;
1524 first = false;
1525 }
1526
1527 for conflict in &self.resource_conflicts {
1528 if !first {
1529 write!(f, ", ")?;
1530 }
1531 write!(f, "{}", conflict)?;
1532 first = false;
1533 }
1534
1535 for conflict in &self.non_send_conflicts {
1536 if !first {
1537 write!(f, ", ")?;
1538 }
1539 write!(f, "{}", conflict)?;
1540 first = false;
1541 }
1542
1543 write!(f, ")")
1544 }
1545}
1546
1547#[cfg(test)]
1552mod tests {
1553 use super::*;
1554 use crate::ecs::Component;
1555
1556 #[derive(Debug, Clone, Copy, PartialEq)]
1558 struct Position {
1559 x: f32,
1560 y: f32,
1561 }
1562 impl Component for Position {}
1563
1564 #[derive(Debug, Clone, Copy, PartialEq)]
1565 struct Velocity {
1566 x: f32,
1567 y: f32,
1568 }
1569 impl Component for Velocity {}
1570
1571 #[derive(Debug, Clone, Copy)]
1572 struct Player;
1573 impl Component for Player {}
1574
1575 mod world_query_trait {
1580 use super::*;
1581
1582 #[test]
1583 fn test_entity_query_init_state() {
1584 let world = World::new();
1585 let _state: () = Entity::init_state(&world);
1586 }
1588
1589 #[test]
1590 fn test_entity_query_matches_all_archetypes() {
1591 use crate::ecs::archetype::{Archetype, ArchetypeId};
1592 use std::collections::BTreeSet;
1593
1594 let state = ();
1595
1596 let empty_arch = Archetype::new(ArchetypeId::EMPTY, BTreeSet::new());
1598 assert!(Entity::matches_archetype(&state, &empty_arch));
1599
1600 let mut components = BTreeSet::new();
1602 components.insert(ComponentId::of::<Position>());
1603 let pos_arch = Archetype::new(ArchetypeId::new(1), components);
1604 assert!(Entity::matches_archetype(&state, &pos_arch));
1605 }
1606
1607 #[test]
1608 fn test_entity_query_fetch_alive() {
1609 let mut world = World::new();
1610 let entity = world.spawn_empty();
1611
1612 let _state: () = Entity::init_state(&world);
1613 let fetched = Entity::fetch(&(), &world, entity);
1614
1615 assert_eq!(fetched, Some(entity));
1616 }
1617
1618 #[test]
1619 fn test_entity_query_fetch_dead() {
1620 let mut world = World::new();
1621 let entity = world.spawn_empty();
1622 world.despawn(entity);
1623
1624 let _state: () = Entity::init_state(&world);
1625 let fetched = Entity::fetch(&(), &world, entity);
1626
1627 assert_eq!(fetched, None);
1628 }
1629
1630 #[test]
1631 fn test_entity_query_is_read_only() {
1632 fn requires_read_only<Q: ReadOnlyWorldQuery>() {}
1634 requires_read_only::<Entity>();
1635 }
1636
1637 #[test]
1638 fn test_entity_query_component_access_empty() {
1639 let state = ();
1640 let access = Entity::component_access(&state);
1641 assert!(access.is_empty());
1642 }
1643 }
1644
1645 mod unit_query {
1650 use super::*;
1651
1652 #[test]
1653 fn test_unit_query_matches_all() {
1654 use crate::ecs::archetype::{Archetype, ArchetypeId};
1655 use std::collections::BTreeSet;
1656
1657 let state = ();
1658
1659 let empty_arch = Archetype::new(ArchetypeId::EMPTY, BTreeSet::new());
1660 assert!(<()>::matches_archetype(&state, &empty_arch));
1661 }
1662
1663 #[test]
1664 fn test_unit_query_fetch_always_succeeds() {
1665 let world = World::new();
1666 let _state: () = <()>::init_state(&world);
1667
1668 let entity = Entity::new(0, 1);
1670 let fetched = <()>::fetch(&(), &world, entity);
1671
1672 assert!(fetched.is_some());
1674 }
1675
1676 #[test]
1677 fn test_unit_query_is_read_only() {
1678 fn requires_read_only<Q: ReadOnlyWorldQuery>() {}
1679 requires_read_only::<()>();
1680 }
1681 }
1682
1683 mod query_state_trait {
1688 use super::*;
1689
1690 #[test]
1691 fn test_component_id_implements_query_state() {
1692 fn requires_query_state<S: QueryState>() {}
1693 requires_query_state::<ComponentId>();
1694 }
1695
1696 #[test]
1697 fn test_unit_implements_query_state() {
1698 fn requires_query_state<S: QueryState>() {}
1699 requires_query_state::<()>();
1700 }
1701
1702 #[test]
1703 fn test_query_state_is_send_sync() {
1704 fn requires_send_sync<S: Send + Sync>() {}
1705 requires_send_sync::<ComponentId>();
1706 requires_send_sync::<()>();
1707 }
1708 }
1709
1710 mod with_filter {
1715 use super::*;
1716 use crate::ecs::archetype::{Archetype, ArchetypeId};
1717 use std::collections::BTreeSet;
1718
1719 #[test]
1720 fn test_with_init_state() {
1721 let world = World::new();
1722 let state = With::<Position>::init_state(&world);
1723 assert_eq!(state, ComponentId::of::<Position>());
1724 }
1725
1726 #[test]
1727 fn test_with_matches_archetype_with_component() {
1728 let mut components = BTreeSet::new();
1729 components.insert(ComponentId::of::<Position>());
1730 let archetype = Archetype::new(ArchetypeId::new(1), components);
1731
1732 let state = ComponentId::of::<Position>();
1733 assert!(With::<Position>::matches_archetype(&state, &archetype));
1734 }
1735
1736 #[test]
1737 fn test_with_does_not_match_archetype_without_component() {
1738 let mut components = BTreeSet::new();
1739 components.insert(ComponentId::of::<Velocity>());
1740 let archetype = Archetype::new(ArchetypeId::new(1), components);
1741
1742 let state = ComponentId::of::<Position>();
1743 assert!(!With::<Position>::matches_archetype(&state, &archetype));
1744 }
1745
1746 #[test]
1747 fn test_with_fetch_entity_with_component() {
1748 let mut world = World::new();
1749 let entity = world.spawn_empty();
1750 world.insert(entity, Position { x: 1.0, y: 2.0 });
1751
1752 let state = With::<Position>::init_state(&world);
1753 let result = With::<Position>::fetch(&state, &world, entity);
1754
1755 assert_eq!(result, Some(()));
1756 }
1757
1758 #[test]
1759 fn test_with_fetch_entity_without_component() {
1760 let mut world = World::new();
1761 let entity = world.spawn_empty();
1762 world.insert(entity, Velocity { x: 1.0, y: 2.0 });
1763
1764 let state = With::<Position>::init_state(&world);
1765 let result = With::<Position>::fetch(&state, &world, entity);
1766
1767 assert_eq!(result, None);
1768 }
1769
1770 #[test]
1771 fn test_with_is_read_only() {
1772 fn requires_read_only<Q: ReadOnlyWorldQuery>() {}
1773 requires_read_only::<With<Position>>();
1774 }
1775
1776 #[test]
1777 fn test_with_component_access_empty() {
1778 let state = ComponentId::of::<Position>();
1779 let access = With::<Position>::component_access(&state);
1780 assert!(access.is_empty());
1782 }
1783 }
1784
1785 mod without_filter {
1790 use super::*;
1791 use crate::ecs::archetype::{Archetype, ArchetypeId};
1792 use std::collections::BTreeSet;
1793
1794 #[test]
1795 fn test_without_init_state() {
1796 let world = World::new();
1797 let state = Without::<Position>::init_state(&world);
1798 assert_eq!(state, ComponentId::of::<Position>());
1799 }
1800
1801 #[test]
1802 fn test_without_matches_archetype_without_component() {
1803 let mut components = BTreeSet::new();
1804 components.insert(ComponentId::of::<Velocity>());
1805 let archetype = Archetype::new(ArchetypeId::new(1), components);
1806
1807 let state = ComponentId::of::<Position>();
1808 assert!(Without::<Position>::matches_archetype(&state, &archetype));
1809 }
1810
1811 #[test]
1812 fn test_without_does_not_match_archetype_with_component() {
1813 let mut components = BTreeSet::new();
1814 components.insert(ComponentId::of::<Position>());
1815 let archetype = Archetype::new(ArchetypeId::new(1), components);
1816
1817 let state = ComponentId::of::<Position>();
1818 assert!(!Without::<Position>::matches_archetype(&state, &archetype));
1819 }
1820
1821 #[test]
1822 fn test_without_fetch_entity_without_component() {
1823 let mut world = World::new();
1824 let entity = world.spawn_empty();
1825 world.insert(entity, Velocity { x: 1.0, y: 2.0 });
1826
1827 let state = Without::<Position>::init_state(&world);
1828 let result = Without::<Position>::fetch(&state, &world, entity);
1829
1830 assert_eq!(result, Some(()));
1831 }
1832
1833 #[test]
1834 fn test_without_fetch_entity_with_component() {
1835 let mut world = World::new();
1836 let entity = world.spawn_empty();
1837 world.insert(entity, Position { x: 1.0, y: 2.0 });
1838
1839 let state = Without::<Position>::init_state(&world);
1840 let result = Without::<Position>::fetch(&state, &world, entity);
1841
1842 assert_eq!(result, None);
1843 }
1844
1845 #[test]
1846 fn test_without_is_read_only() {
1847 fn requires_read_only<Q: ReadOnlyWorldQuery>() {}
1848 requires_read_only::<Without<Position>>();
1849 }
1850
1851 #[test]
1852 fn test_without_matches_empty_archetype() {
1853 let archetype = Archetype::new(ArchetypeId::EMPTY, BTreeSet::new());
1854 let state = ComponentId::of::<Position>();
1855 assert!(Without::<Position>::matches_archetype(&state, &archetype));
1856 }
1857 }
1858
1859 mod component_ref {
1864 use super::*;
1865 use crate::ecs::archetype::{Archetype, ArchetypeId};
1866 use std::collections::BTreeSet;
1867
1868 #[test]
1869 fn test_ref_init_state() {
1870 let world = World::new();
1871 let state = <&Position>::init_state(&world);
1872 assert_eq!(state, ComponentId::of::<Position>());
1873 }
1874
1875 #[test]
1876 fn test_ref_matches_archetype_with_component() {
1877 let mut components = BTreeSet::new();
1878 components.insert(ComponentId::of::<Position>());
1879 let archetype = Archetype::new(ArchetypeId::new(1), components);
1880
1881 let state = ComponentId::of::<Position>();
1882 assert!(<&Position>::matches_archetype(&state, &archetype));
1883 }
1884
1885 #[test]
1886 fn test_ref_does_not_match_archetype_without_component() {
1887 let mut components = BTreeSet::new();
1888 components.insert(ComponentId::of::<Velocity>());
1889 let archetype = Archetype::new(ArchetypeId::new(1), components);
1890
1891 let state = ComponentId::of::<Position>();
1892 assert!(!<&Position>::matches_archetype(&state, &archetype));
1893 }
1894
1895 #[test]
1896 fn test_ref_does_not_match_empty_archetype() {
1897 let archetype = Archetype::new(ArchetypeId::EMPTY, BTreeSet::new());
1898
1899 let state = ComponentId::of::<Position>();
1900 assert!(!<&Position>::matches_archetype(&state, &archetype));
1901 }
1902
1903 #[test]
1904 fn test_ref_fetch_entity_with_component() {
1905 let mut world = World::new();
1906 let entity = world.spawn_empty();
1907 world.insert(entity, Position { x: 1.0, y: 2.0 });
1908
1909 let state = <&Position>::init_state(&world);
1910 let result = <&Position>::fetch(&state, &world, entity);
1911
1912 assert!(result.is_some());
1913 let pos = result.unwrap();
1914 assert_eq!(pos.x, 1.0);
1915 assert_eq!(pos.y, 2.0);
1916 }
1917
1918 #[test]
1919 fn test_ref_fetch_entity_without_component() {
1920 let mut world = World::new();
1921 let entity = world.spawn_empty();
1922 world.insert(entity, Velocity { x: 1.0, y: 2.0 });
1923
1924 let state = <&Position>::init_state(&world);
1925 let result = <&Position>::fetch(&state, &world, entity);
1926
1927 assert!(result.is_none());
1928 }
1929
1930 #[test]
1931 fn test_ref_fetch_dead_entity() {
1932 let mut world = World::new();
1933 let entity = world.spawn_empty();
1934 world.insert(entity, Position { x: 1.0, y: 2.0 });
1935 world.despawn(entity);
1936
1937 let state = <&Position>::init_state(&world);
1938 let result = <&Position>::fetch(&state, &world, entity);
1939
1940 assert!(result.is_none());
1941 }
1942
1943 #[test]
1944 fn test_ref_fetch_placeholder_entity() {
1945 let world = World::new();
1946
1947 let state = <&Position>::init_state(&world);
1948 let result = <&Position>::fetch(&state, &world, Entity::PLACEHOLDER);
1949
1950 assert!(result.is_none());
1951 }
1952
1953 #[test]
1954 fn test_ref_is_read_only() {
1955 fn requires_read_only<Q: ReadOnlyWorldQuery>() {}
1956 requires_read_only::<&Position>();
1957 requires_read_only::<&Velocity>();
1958 }
1959
1960 #[test]
1961 fn test_ref_component_access_contains_component_id() {
1962 let state = ComponentId::of::<Position>();
1963 let access = <&Position>::component_access(&state);
1964
1965 assert_eq!(access.len(), 1);
1966 assert!(access.contains(&ComponentId::of::<Position>()));
1967 }
1968
1969 #[test]
1970 fn test_ref_component_access_does_not_contain_other_components() {
1971 let state = ComponentId::of::<Position>();
1972 let access = <&Position>::component_access(&state);
1973
1974 assert!(!access.contains(&ComponentId::of::<Velocity>()));
1975 }
1976
1977 #[test]
1978 fn test_ref_multiple_entities_same_component() {
1979 let mut world = World::new();
1980
1981 let e1 = world.spawn_empty();
1982 world.insert(e1, Position { x: 1.0, y: 2.0 });
1983
1984 let e2 = world.spawn_empty();
1985 world.insert(e2, Position { x: 3.0, y: 4.0 });
1986
1987 let e3 = world.spawn_empty();
1988 world.insert(e3, Position { x: 5.0, y: 6.0 });
1989
1990 let state = <&Position>::init_state(&world);
1991
1992 let p1 = <&Position>::fetch(&state, &world, e1).unwrap();
1993 let p2 = <&Position>::fetch(&state, &world, e2).unwrap();
1994 let p3 = <&Position>::fetch(&state, &world, e3).unwrap();
1995
1996 assert_eq!(p1, &Position { x: 1.0, y: 2.0 });
1997 assert_eq!(p2, &Position { x: 3.0, y: 4.0 });
1998 assert_eq!(p3, &Position { x: 5.0, y: 6.0 });
1999 }
2000
2001 #[test]
2002 fn test_ref_different_component_types() {
2003 let mut world = World::new();
2004 let entity = world.spawn_empty();
2005 world.insert(entity, Position { x: 1.0, y: 2.0 });
2006 world.insert(entity, Velocity { x: 3.0, y: 4.0 });
2007
2008 let pos_state = <&Position>::init_state(&world);
2009 let vel_state = <&Velocity>::init_state(&world);
2010
2011 let pos = <&Position>::fetch(&pos_state, &world, entity).unwrap();
2012 let vel = <&Velocity>::fetch(&vel_state, &world, entity).unwrap();
2013
2014 assert_eq!(pos, &Position { x: 1.0, y: 2.0 });
2015 assert_eq!(vel, &Velocity { x: 3.0, y: 4.0 });
2016 }
2017
2018 #[test]
2019 fn test_ref_fetch_after_component_update() {
2020 let mut world = World::new();
2021 let entity = world.spawn_empty();
2022 world.insert(entity, Position { x: 1.0, y: 2.0 });
2023
2024 let state = <&Position>::init_state(&world);
2025
2026 let pos1 = <&Position>::fetch(&state, &world, entity).unwrap();
2028 assert_eq!(pos1, &Position { x: 1.0, y: 2.0 });
2029
2030 world.insert(entity, Position { x: 10.0, y: 20.0 });
2032
2033 let pos2 = <&Position>::fetch(&state, &world, entity).unwrap();
2035 assert_eq!(pos2, &Position { x: 10.0, y: 20.0 });
2036 }
2037
2038 #[test]
2039 fn test_ref_matches_archetype_with_multiple_components() {
2040 let mut components = BTreeSet::new();
2041 components.insert(ComponentId::of::<Position>());
2042 components.insert(ComponentId::of::<Velocity>());
2043 components.insert(ComponentId::of::<Player>());
2044 let archetype = Archetype::new(ArchetypeId::new(1), components);
2045
2046 let pos_state = ComponentId::of::<Position>();
2047 let vel_state = ComponentId::of::<Velocity>();
2048
2049 assert!(<&Position>::matches_archetype(&pos_state, &archetype));
2050 assert!(<&Velocity>::matches_archetype(&vel_state, &archetype));
2051 }
2052
2053 #[test]
2054 fn test_ref_fetch_returns_correct_reference_type() {
2055 let mut world = World::new();
2056 let entity = world.spawn_empty();
2057 world.insert(entity, Position { x: 42.0, y: 99.0 });
2058
2059 let state = <&Position>::init_state(&world);
2060 let result: Option<&Position> = <&Position>::fetch(&state, &world, entity);
2061
2062 assert!(result.is_some());
2064 }
2065
2066 #[test]
2067 fn test_ref_fetch_stale_entity() {
2068 let mut world = World::new();
2069
2070 let entity = world.spawn_empty();
2072 world.insert(entity, Position { x: 1.0, y: 2.0 });
2073 world.despawn(entity);
2074
2075 let new_entity = world.spawn_empty();
2077 world.insert(new_entity, Position { x: 99.0, y: 99.0 });
2078
2079 let state = <&Position>::init_state(&world);
2080
2081 let result = <&Position>::fetch(&state, &world, entity);
2083 assert!(result.is_none());
2084
2085 let new_result = <&Position>::fetch(&state, &world, new_entity);
2087 assert!(new_result.is_some());
2088 assert_eq!(new_result.unwrap(), &Position { x: 99.0, y: 99.0 });
2089 }
2090
2091 #[test]
2092 fn test_ref_state_is_component_id() {
2093 fn check_state_type<T: crate::ecs::Component>() {
2095 let world = World::new();
2096 let state: ComponentId = <&T>::init_state(&world);
2097 assert_eq!(state, ComponentId::of::<T>());
2098 }
2099
2100 check_state_type::<Position>();
2101 check_state_type::<Velocity>();
2102 }
2103
2104 #[test]
2107 fn test_ref_implements_world_query() {
2108 fn requires_world_query<Q: WorldQuery>() {}
2109 requires_world_query::<&Position>();
2110 requires_world_query::<&Velocity>();
2111 requires_world_query::<&Player>();
2112 }
2113
2114 #[test]
2115 fn test_ref_state_implements_query_state() {
2116 fn requires_query_state<S: QueryState>() {}
2117 requires_query_state::<ComponentId>();
2119 }
2120 }
2121
2122 mod mut_component_ref {
2127 use super::*;
2128 use crate::ecs::archetype::{Archetype, ArchetypeId};
2129 use std::collections::BTreeSet;
2130
2131 #[test]
2132 fn test_mut_ref_init_state() {
2133 let world = World::new();
2134 let state = <&mut Position>::init_state(&world);
2135 assert_eq!(state.component_id, ComponentId::of::<Position>());
2136 }
2137
2138 #[test]
2139 fn test_mut_ref_state_is_mut_state() {
2140 fn check_state_type<T: crate::ecs::Component>() {
2142 let world = World::new();
2143 let state: MutState = <&mut T>::init_state(&world);
2144 assert_eq!(state.component_id, ComponentId::of::<T>());
2145 }
2146
2147 check_state_type::<Position>();
2148 check_state_type::<Velocity>();
2149 }
2150
2151 #[test]
2152 fn test_mut_ref_matches_archetype_with_component() {
2153 let mut components = BTreeSet::new();
2154 components.insert(ComponentId::of::<Position>());
2155 let archetype = Archetype::new(ArchetypeId::new(1), components);
2156
2157 let state = MutState::of::<Position>();
2158 assert!(<&mut Position>::matches_archetype(&state, &archetype));
2159 }
2160
2161 #[test]
2162 fn test_mut_ref_does_not_match_archetype_without_component() {
2163 let mut components = BTreeSet::new();
2164 components.insert(ComponentId::of::<Velocity>());
2165 let archetype = Archetype::new(ArchetypeId::new(1), components);
2166
2167 let state = MutState::of::<Position>();
2168 assert!(!<&mut Position>::matches_archetype(&state, &archetype));
2169 }
2170
2171 #[test]
2172 fn test_mut_ref_does_not_match_empty_archetype() {
2173 let archetype = Archetype::new(ArchetypeId::EMPTY, BTreeSet::new());
2174
2175 let state = MutState::of::<Position>();
2176 assert!(!<&mut Position>::matches_archetype(&state, &archetype));
2177 }
2178
2179 #[test]
2180 fn test_mut_ref_fetch_returns_none() {
2181 let mut world = World::new();
2183 let entity = world.spawn_empty();
2184 world.insert(entity, Position { x: 1.0, y: 2.0 });
2185
2186 let state = <&mut Position>::init_state(&world);
2187 let result = <&mut Position>::fetch(&state, &world, entity);
2188
2189 assert!(result.is_none());
2191 }
2192
2193 #[test]
2194 fn test_mut_ref_fetch_mut_entity_with_component() {
2195 let mut world = World::new();
2196 let entity = world.spawn_empty();
2197 world.insert(entity, Position { x: 1.0, y: 2.0 });
2198
2199 let state = <&mut Position>::init_state(&world);
2200 let result = <&mut Position>::fetch_mut(&state, &mut world, entity);
2201
2202 assert!(result.is_some());
2203 let pos = result.unwrap();
2204 assert_eq!(pos.x, 1.0);
2205 assert_eq!(pos.y, 2.0);
2206 }
2207
2208 #[test]
2209 fn test_mut_ref_fetch_mut_and_modify() {
2210 let mut world = World::new();
2211 let entity = world.spawn_empty();
2212 world.insert(entity, Position { x: 1.0, y: 2.0 });
2213
2214 let state = <&mut Position>::init_state(&world);
2215
2216 if let Some(pos) = <&mut Position>::fetch_mut(&state, &mut world, entity) {
2218 pos.x += 10.0;
2219 pos.y += 20.0;
2220 }
2221
2222 let pos = world.get::<Position>(entity).unwrap();
2224 assert_eq!(pos.x, 11.0);
2225 assert_eq!(pos.y, 22.0);
2226 }
2227
2228 #[test]
2229 fn test_mut_ref_fetch_mut_entity_without_component() {
2230 let mut world = World::new();
2231 let entity = world.spawn_empty();
2232 world.insert(entity, Velocity { x: 1.0, y: 2.0 });
2233
2234 let state = <&mut Position>::init_state(&world);
2235 let result = <&mut Position>::fetch_mut(&state, &mut world, entity);
2236
2237 assert!(result.is_none());
2238 }
2239
2240 #[test]
2241 fn test_mut_ref_fetch_mut_dead_entity() {
2242 let mut world = World::new();
2243 let entity = world.spawn_empty();
2244 world.insert(entity, Position { x: 1.0, y: 2.0 });
2245 world.despawn(entity);
2246
2247 let state = <&mut Position>::init_state(&world);
2248 let result = <&mut Position>::fetch_mut(&state, &mut world, entity);
2249
2250 assert!(result.is_none());
2251 }
2252
2253 #[test]
2254 fn test_mut_ref_fetch_mut_placeholder_entity() {
2255 let mut world = World::new();
2256
2257 let state = <&mut Position>::init_state(&world);
2258 let result = <&mut Position>::fetch_mut(&state, &mut world, Entity::PLACEHOLDER);
2259
2260 assert!(result.is_none());
2261 }
2262
2263 #[test]
2264 fn test_mut_ref_is_not_read_only() {
2265 fn requires_world_query<Q: WorldQuery>() {}
2272 requires_world_query::<&mut Position>();
2273 }
2274
2275 #[test]
2276 fn test_mut_ref_component_access_contains_component_id() {
2277 let state = MutState::of::<Position>();
2278 let access = <&mut Position>::component_access(&state);
2279
2280 assert_eq!(access.len(), 1);
2281 assert!(access.contains(&ComponentId::of::<Position>()));
2282 }
2283
2284 #[test]
2285 fn test_mut_ref_component_access_does_not_contain_other_components() {
2286 let state = MutState::of::<Position>();
2287 let access = <&mut Position>::component_access(&state);
2288
2289 assert!(!access.contains(&ComponentId::of::<Velocity>()));
2290 }
2291
2292 #[test]
2293 fn test_mut_ref_fetch_mut_stale_entity() {
2294 let mut world = World::new();
2295
2296 let entity = world.spawn_empty();
2298 world.insert(entity, Position { x: 1.0, y: 2.0 });
2299 world.despawn(entity);
2300
2301 let new_entity = world.spawn_empty();
2303 world.insert(new_entity, Position { x: 99.0, y: 99.0 });
2304
2305 let state = <&mut Position>::init_state(&world);
2306
2307 let result = <&mut Position>::fetch_mut(&state, &mut world, entity);
2309 assert!(result.is_none());
2310
2311 let new_result = <&mut Position>::fetch_mut(&state, &mut world, new_entity);
2313 assert!(new_result.is_some());
2314 assert_eq!(new_result.unwrap().x, 99.0);
2315 }
2316
2317 #[test]
2318 fn test_mut_ref_implements_world_query() {
2319 fn requires_world_query<Q: WorldQuery>() {}
2320 requires_world_query::<&mut Position>();
2321 requires_world_query::<&mut Velocity>();
2322 requires_world_query::<&mut Player>();
2323 }
2324
2325 #[test]
2326 fn test_mut_state_implements_query_state() {
2327 fn requires_query_state<S: QueryState>() {}
2328 requires_query_state::<MutState>();
2329 }
2330
2331 #[test]
2332 fn test_mut_ref_matches_archetype_with_multiple_components() {
2333 let mut components = BTreeSet::new();
2334 components.insert(ComponentId::of::<Position>());
2335 components.insert(ComponentId::of::<Velocity>());
2336 components.insert(ComponentId::of::<Player>());
2337 let archetype = Archetype::new(ArchetypeId::new(1), components);
2338
2339 let pos_state = MutState::of::<Position>();
2340 let vel_state = MutState::of::<Velocity>();
2341
2342 assert!(<&mut Position>::matches_archetype(&pos_state, &archetype));
2343 assert!(<&mut Velocity>::matches_archetype(&vel_state, &archetype));
2344 }
2345
2346 #[test]
2347 fn test_mut_ref_fetch_mut_returns_correct_reference_type() {
2348 let mut world = World::new();
2349 let entity = world.spawn_empty();
2350 world.insert(entity, Position { x: 42.0, y: 99.0 });
2351
2352 let state = <&mut Position>::init_state(&world);
2353 let result: Option<&mut Position> =
2354 <&mut Position>::fetch_mut(&state, &mut world, entity);
2355
2356 assert!(result.is_some());
2358 }
2359
2360 #[test]
2361 fn test_mut_ref_different_component_types() {
2362 let mut world = World::new();
2363 let entity = world.spawn_empty();
2364 world.insert(entity, Position { x: 1.0, y: 2.0 });
2365 world.insert(entity, Velocity { x: 3.0, y: 4.0 });
2366
2367 let pos_state = <&mut Position>::init_state(&world);
2368
2369 if let Some(pos) = <&mut Position>::fetch_mut(&pos_state, &mut world, entity) {
2371 pos.x = 100.0;
2372 }
2373
2374 let vel = world.get::<Velocity>(entity).unwrap();
2376 assert_eq!(vel.x, 3.0);
2377 assert_eq!(vel.y, 4.0);
2378
2379 let pos = world.get::<Position>(entity).unwrap();
2381 assert_eq!(pos.x, 100.0);
2382 }
2383 }
2384
2385 mod access_conflict {
2390 use super::*;
2391
2392 #[test]
2393 fn test_access_new_is_empty() {
2394 let access = Access::new();
2395 assert!(access.is_read_only());
2396 assert_eq!(access.writes().len(), 0);
2397 assert_eq!(access.reads().count(), 0);
2398 }
2399
2400 #[test]
2401 fn test_access_add_read() {
2402 let mut access = Access::new();
2403 let id = ComponentId::of::<Position>();
2404 access.add_read(id);
2405
2406 assert!(access.is_read_only());
2407 assert!(access.reads().any(|&x| x == id));
2408 assert!(!access.writes().contains(&id));
2409 }
2410
2411 #[test]
2412 fn test_access_add_write() {
2413 let mut access = Access::new();
2414 let id = ComponentId::of::<Position>();
2415 access.add_write(id);
2416
2417 assert!(!access.is_read_only());
2418 assert!(access.writes().contains(&id));
2419 }
2420
2421 #[test]
2422 fn test_access_write_counts_as_read() {
2423 let mut access = Access::new();
2424 let id = ComponentId::of::<Position>();
2425 access.add_write(id);
2426
2427 assert!(access.writes().contains(&id));
2429 assert!(access.reads().any(|&x| x == id));
2431 }
2432
2433 #[test]
2434 fn test_access_reads_only() {
2435 let mut access = Access::new();
2436 let pos_id = ComponentId::of::<Position>();
2437 let vel_id = ComponentId::of::<Velocity>();
2438
2439 access.add_read(pos_id);
2440 access.add_write(vel_id);
2441
2442 let reads_only: Vec<_> = access.reads_only().cloned().collect();
2444 assert!(reads_only.contains(&pos_id));
2445 assert!(!reads_only.contains(&vel_id));
2446 }
2447
2448 #[test]
2449 fn test_access_no_conflict_between_reads() {
2450 let mut access1 = Access::new();
2451 let mut access2 = Access::new();
2452 let id = ComponentId::of::<Position>();
2453
2454 access1.add_read(id);
2455 access2.add_read(id);
2456
2457 assert!(!access1.conflicts_with(&access2));
2459 assert!(!access2.conflicts_with(&access1));
2460 }
2461
2462 #[test]
2463 fn test_access_conflict_write_read() {
2464 let mut access1 = Access::new();
2465 let mut access2 = Access::new();
2466 let id = ComponentId::of::<Position>();
2467
2468 access1.add_write(id);
2469 access2.add_read(id);
2470
2471 assert!(access1.conflicts_with(&access2));
2473 assert!(access2.conflicts_with(&access1));
2474 }
2475
2476 #[test]
2477 fn test_access_conflict_write_write() {
2478 let mut access1 = Access::new();
2479 let mut access2 = Access::new();
2480 let id = ComponentId::of::<Position>();
2481
2482 access1.add_write(id);
2483 access2.add_write(id);
2484
2485 assert!(access1.conflicts_with(&access2));
2487 assert!(access2.conflicts_with(&access1));
2488 }
2489
2490 #[test]
2491 fn test_access_no_conflict_different_components() {
2492 let mut access1 = Access::new();
2493 let mut access2 = Access::new();
2494
2495 access1.add_write(ComponentId::of::<Position>());
2496 access2.add_write(ComponentId::of::<Velocity>());
2497
2498 assert!(!access1.conflicts_with(&access2));
2500 assert!(!access2.conflicts_with(&access1));
2501 }
2502
2503 #[test]
2504 fn test_access_no_conflict_read_different_write() {
2505 let mut access1 = Access::new();
2506 let mut access2 = Access::new();
2507
2508 access1.add_read(ComponentId::of::<Position>());
2509 access2.add_write(ComponentId::of::<Velocity>());
2510
2511 assert!(!access1.conflicts_with(&access2));
2513 assert!(!access2.conflicts_with(&access1));
2514 }
2515
2516 #[test]
2517 fn test_access_extend() {
2518 let mut access1 = Access::new();
2519 let mut access2 = Access::new();
2520
2521 access1.add_read(ComponentId::of::<Position>());
2522 access2.add_write(ComponentId::of::<Velocity>());
2523
2524 access1.extend(&access2);
2525
2526 assert!(access1.reads().any(|&x| x == ComponentId::of::<Position>()));
2527 assert!(access1.writes().contains(&ComponentId::of::<Velocity>()));
2528 }
2529
2530 #[test]
2531 fn test_access_is_read_only() {
2532 let mut read_access = Access::new();
2533 read_access.add_read(ComponentId::of::<Position>());
2534 assert!(read_access.is_read_only());
2535
2536 let mut write_access = Access::new();
2537 write_access.add_write(ComponentId::of::<Position>());
2538 assert!(!write_access.is_read_only());
2539 }
2540
2541 #[test]
2542 fn test_access_complex_scenario() {
2543 let mut access_a = Access::new();
2549 access_a.add_read(ComponentId::of::<Position>());
2550 access_a.add_write(ComponentId::of::<Velocity>());
2551
2552 let mut access_b = Access::new();
2553 access_b.add_read(ComponentId::of::<Position>());
2554 access_b.add_read(ComponentId::of::<Velocity>());
2555
2556 assert!(access_a.conflicts_with(&access_b));
2558 assert!(access_b.conflicts_with(&access_a));
2559 }
2560
2561 #[test]
2562 fn test_access_no_conflict_complex() {
2563 let mut access_a = Access::new();
2568 access_a.add_write(ComponentId::of::<Position>());
2569
2570 let mut access_b = Access::new();
2571 access_b.add_write(ComponentId::of::<Velocity>());
2572 access_b.add_read(ComponentId::of::<Player>());
2573
2574 assert!(!access_a.conflicts_with(&access_b));
2575 assert!(!access_b.conflicts_with(&access_a));
2576 }
2577
2578 #[test]
2579 fn test_access_is_empty() {
2580 let access = Access::new();
2581 assert!(access.is_empty());
2582
2583 let mut not_empty = Access::new();
2584 not_empty.add_read(ComponentId::of::<Position>());
2585 assert!(!not_empty.is_empty());
2586 }
2587
2588 #[test]
2589 fn test_access_clear() {
2590 let mut access = Access::new();
2591 access.add_read(ComponentId::of::<Position>());
2592 access.add_write(ComponentId::of::<Velocity>());
2593
2594 assert!(!access.is_empty());
2595 access.clear();
2596 assert!(access.is_empty());
2597 }
2598
2599 #[test]
2604 fn test_get_conflicts_no_conflict() {
2605 let mut access1 = Access::new();
2606 access1.add_read(ComponentId::of::<Position>());
2607
2608 let mut access2 = Access::new();
2609 access2.add_read(ComponentId::of::<Position>());
2610
2611 assert!(access1.get_conflicts(&access2).is_none());
2612 }
2613
2614 #[test]
2615 fn test_get_conflicts_write_read() {
2616 let mut access1 = Access::new();
2617 access1.add_write(ComponentId::of::<Position>());
2618
2619 let mut access2 = Access::new();
2620 access2.add_read(ComponentId::of::<Position>());
2621
2622 let conflict = access1.get_conflicts(&access2);
2623 assert!(conflict.is_some());
2624
2625 let conflict = conflict.unwrap();
2626 assert_eq!(conflict.component_count(), 1);
2627 assert!(!conflict.has_write_write());
2628
2629 let comp_conflict = &conflict.component_conflicts()[0];
2630 assert_eq!(comp_conflict.component_id, ComponentId::of::<Position>());
2631 assert_eq!(comp_conflict.first_access, AccessType::Write);
2632 assert_eq!(comp_conflict.second_access, AccessType::Read);
2633 }
2634
2635 #[test]
2636 fn test_get_conflicts_write_write() {
2637 let mut access1 = Access::new();
2638 access1.add_write(ComponentId::of::<Position>());
2639
2640 let mut access2 = Access::new();
2641 access2.add_write(ComponentId::of::<Position>());
2642
2643 let conflict = access1.get_conflicts(&access2);
2644 assert!(conflict.is_some());
2645
2646 let conflict = conflict.unwrap();
2647 assert!(conflict.has_write_write());
2648
2649 let comp_conflict = &conflict.component_conflicts()[0];
2650 assert!(comp_conflict.is_write_write());
2651 }
2652
2653 #[test]
2654 fn test_get_conflicts_multiple_components() {
2655 let mut access1 = Access::new();
2656 access1.add_write(ComponentId::of::<Position>());
2657 access1.add_write(ComponentId::of::<Velocity>());
2658
2659 let mut access2 = Access::new();
2660 access2.add_read(ComponentId::of::<Position>());
2661 access2.add_read(ComponentId::of::<Velocity>());
2662
2663 let conflict = access1.get_conflicts(&access2).unwrap();
2664 assert_eq!(conflict.component_count(), 2);
2665 assert_eq!(conflict.total_count(), 2);
2666 }
2667
2668 #[test]
2669 fn test_get_conflicts_partial() {
2670 let mut access1 = Access::new();
2673 access1.add_write(ComponentId::of::<Position>());
2674
2675 let mut access2 = Access::new();
2676 access2.add_read(ComponentId::of::<Position>());
2677 access2.add_write(ComponentId::of::<Velocity>());
2678
2679 let conflict = access1.get_conflicts(&access2).unwrap();
2680 assert_eq!(conflict.component_count(), 1);
2682
2683 let conflicting: Vec<_> = conflict.conflicting_components().collect();
2684 assert_eq!(conflicting.len(), 1);
2685 assert_eq!(conflicting[0], ComponentId::of::<Position>());
2686 }
2687
2688 #[test]
2689 fn test_get_conflicts_read_vs_write() {
2690 let mut access1 = Access::new();
2692 access1.add_read(ComponentId::of::<Position>());
2693
2694 let mut access2 = Access::new();
2695 access2.add_write(ComponentId::of::<Position>());
2696
2697 let conflict = access1.get_conflicts(&access2).unwrap();
2698 assert_eq!(conflict.component_count(), 1);
2699
2700 let comp_conflict = &conflict.component_conflicts()[0];
2701 assert_eq!(comp_conflict.first_access, AccessType::Read);
2702 assert_eq!(comp_conflict.second_access, AccessType::Write);
2703 assert!(comp_conflict.is_read_write());
2704 }
2705 }
2706
2707 mod conflict_info {
2712 use super::*;
2713
2714 #[test]
2715 fn test_conflict_info_new() {
2716 let info = ConflictInfo::new(
2717 ComponentId::of::<Position>(),
2718 AccessType::Write,
2719 AccessType::Read,
2720 );
2721
2722 assert_eq!(info.component_id, ComponentId::of::<Position>());
2723 assert_eq!(info.first_access, AccessType::Write);
2724 assert_eq!(info.second_access, AccessType::Read);
2725 }
2726
2727 #[test]
2728 fn test_conflict_info_is_write_write() {
2729 let write_write = ConflictInfo::new(
2730 ComponentId::of::<Position>(),
2731 AccessType::Write,
2732 AccessType::Write,
2733 );
2734 assert!(write_write.is_write_write());
2735
2736 let write_read = ConflictInfo::new(
2737 ComponentId::of::<Position>(),
2738 AccessType::Write,
2739 AccessType::Read,
2740 );
2741 assert!(!write_read.is_write_write());
2742 }
2743
2744 #[test]
2745 fn test_conflict_info_is_read_write() {
2746 let write_read = ConflictInfo::new(
2747 ComponentId::of::<Position>(),
2748 AccessType::Write,
2749 AccessType::Read,
2750 );
2751 assert!(write_read.is_read_write());
2752
2753 let read_write = ConflictInfo::new(
2754 ComponentId::of::<Position>(),
2755 AccessType::Read,
2756 AccessType::Write,
2757 );
2758 assert!(read_write.is_read_write());
2759
2760 let write_write = ConflictInfo::new(
2761 ComponentId::of::<Position>(),
2762 AccessType::Write,
2763 AccessType::Write,
2764 );
2765 assert!(!write_write.is_read_write());
2766 }
2767
2768 #[test]
2769 fn test_conflict_info_display() {
2770 let info = ConflictInfo::new(
2771 ComponentId::of::<Position>(),
2772 AccessType::Write,
2773 AccessType::Read,
2774 );
2775 let display = format!("{}", info);
2776 assert!(display.contains("Component"));
2777 assert!(display.contains("Write"));
2778 assert!(display.contains("Read"));
2779 }
2780 }
2781
2782 mod access_conflict_struct {
2787 use super::*;
2788
2789 #[test]
2790 fn test_access_conflict_new() {
2791 let conflict = AccessConflict::new();
2792 assert!(conflict.is_empty());
2793 assert_eq!(conflict.component_count(), 0);
2794 assert_eq!(conflict.resource_count(), 0);
2795 assert_eq!(conflict.non_send_count(), 0);
2796 assert_eq!(conflict.total_count(), 0);
2797 }
2798
2799 #[test]
2800 fn test_access_conflict_default() {
2801 let conflict: AccessConflict = Default::default();
2802 assert!(conflict.is_empty());
2803 }
2804
2805 #[test]
2806 fn test_access_conflict_display() {
2807 let mut access1 = Access::new();
2808 access1.add_write(ComponentId::of::<Position>());
2809
2810 let mut access2 = Access::new();
2811 access2.add_read(ComponentId::of::<Position>());
2812
2813 let conflict = access1.get_conflicts(&access2).unwrap();
2814 let display = format!("{}", conflict);
2815
2816 assert!(display.contains("AccessConflict"));
2817 assert!(display.contains("Component"));
2818 }
2819
2820 #[test]
2821 fn test_access_conflict_has_write_write() {
2822 let mut access1 = Access::new();
2823 access1.add_write(ComponentId::of::<Position>());
2824
2825 let mut access2 = Access::new();
2826 access2.add_write(ComponentId::of::<Position>());
2827
2828 let conflict = access1.get_conflicts(&access2).unwrap();
2829 assert!(conflict.has_write_write());
2830 }
2831
2832 #[test]
2833 fn test_access_conflict_has_write_write_false() {
2834 let mut access1 = Access::new();
2835 access1.add_write(ComponentId::of::<Position>());
2836
2837 let mut access2 = Access::new();
2838 access2.add_read(ComponentId::of::<Position>());
2839
2840 let conflict = access1.get_conflicts(&access2).unwrap();
2841 assert!(!conflict.has_write_write());
2842 }
2843
2844 #[test]
2845 fn test_access_conflict_conflicting_components_iter() {
2846 let mut access1 = Access::new();
2847 access1.add_write(ComponentId::of::<Position>());
2848 access1.add_write(ComponentId::of::<Velocity>());
2849
2850 let mut access2 = Access::new();
2851 access2.add_read(ComponentId::of::<Position>());
2852 access2.add_read(ComponentId::of::<Velocity>());
2853
2854 let conflict = access1.get_conflicts(&access2).unwrap();
2855 let components: Vec<_> = conflict.conflicting_components().collect();
2856
2857 assert_eq!(components.len(), 2);
2858 assert!(components.contains(&ComponentId::of::<Position>()));
2859 assert!(components.contains(&ComponentId::of::<Velocity>()));
2860 }
2861
2862 #[test]
2863 fn test_access_conflict_clone() {
2864 let mut access1 = Access::new();
2865 access1.add_write(ComponentId::of::<Position>());
2866
2867 let mut access2 = Access::new();
2868 access2.add_read(ComponentId::of::<Position>());
2869
2870 let conflict = access1.get_conflicts(&access2).unwrap();
2871 let cloned = conflict.clone();
2872
2873 assert_eq!(conflict.total_count(), cloned.total_count());
2874 }
2875 }
2876
2877 mod mut_state {
2882 use super::*;
2883
2884 #[test]
2885 fn test_mut_state_of() {
2886 let state = MutState::of::<Position>();
2887 assert_eq!(state.component_id, ComponentId::of::<Position>());
2888 }
2889
2890 #[test]
2891 fn test_mut_state_different_types() {
2892 let pos_state = MutState::of::<Position>();
2893 let vel_state = MutState::of::<Velocity>();
2894
2895 assert_ne!(pos_state.component_id, vel_state.component_id);
2896 }
2897
2898 #[test]
2899 fn test_mut_state_implements_query_state() {
2900 fn requires_query_state<S: QueryState>() {}
2901 requires_query_state::<MutState>();
2902 }
2903
2904 #[test]
2905 fn test_mut_state_is_send_sync() {
2906 fn requires_send_sync<T: Send + Sync>() {}
2907 requires_send_sync::<MutState>();
2908 }
2909
2910 #[test]
2911 fn test_mut_state_is_clone() {
2912 let state = MutState::of::<Position>();
2913 let cloned = state.clone();
2914 assert_eq!(state, cloned);
2915 }
2916
2917 #[test]
2918 fn test_mut_state_debug() {
2919 let state = MutState::of::<Position>();
2920 let debug_str = format!("{:?}", state);
2921 assert!(debug_str.contains("MutState"));
2923 }
2924 }
2925
2926 mod write_access {
2931 use super::*;
2932
2933 #[test]
2934 fn test_write_access_new() {
2935 let id = ComponentId::of::<Position>();
2936 let access = WriteAccess(id);
2937 assert_eq!(access.0, id);
2938 }
2939
2940 #[test]
2941 fn test_write_access_equality() {
2942 let id1 = ComponentId::of::<Position>();
2943 let id2 = ComponentId::of::<Position>();
2944 let id3 = ComponentId::of::<Velocity>();
2945
2946 assert_eq!(WriteAccess(id1), WriteAccess(id2));
2947 assert_ne!(WriteAccess(id1), WriteAccess(id3));
2948 }
2949
2950 #[test]
2951 fn test_write_access_hash() {
2952 use std::collections::HashSet;
2953
2954 let id1 = ComponentId::of::<Position>();
2955 let id2 = ComponentId::of::<Velocity>();
2956
2957 let mut set = HashSet::new();
2958 set.insert(WriteAccess(id1));
2959 set.insert(WriteAccess(id2));
2960
2961 assert_eq!(set.len(), 2);
2962 assert!(set.contains(&WriteAccess(id1)));
2963 assert!(set.contains(&WriteAccess(id2)));
2964 }
2965
2966 #[test]
2967 fn test_write_access_ordering() {
2968 use std::collections::BTreeSet;
2969
2970 let id1 = ComponentId::of::<Position>();
2971 let id2 = ComponentId::of::<Velocity>();
2972
2973 let mut set = BTreeSet::new();
2974 set.insert(WriteAccess(id1));
2975 set.insert(WriteAccess(id2));
2976
2977 assert_eq!(set.len(), 2);
2979 }
2980 }
2981
2982 mod documentation {
2987 use super::*;
2988
2989 #[test]
2990 fn test_world_query_trait_documentation_example() {
2991 fn query_requires_world_query<Q: WorldQuery>() {}
2993 query_requires_world_query::<Entity>();
2994 }
2995
2996 #[test]
2997 fn test_query_state_documentation_example() {
2998 fn requires_query_state<S: QueryState>() {}
2999 requires_query_state::<ComponentId>();
3000 }
3001
3002 #[test]
3003 fn test_with_filter_usage_documentation() {
3004 let mut world = World::new();
3006 let e1 = world.spawn_empty();
3007 world.insert(e1, Position { x: 0.0, y: 0.0 });
3008 world.insert(e1, Player);
3009
3010 let e2 = world.spawn_empty();
3011 world.insert(e2, Position { x: 1.0, y: 1.0 });
3012 let state = With::<Player>::init_state(&world);
3015
3016 assert!(With::<Player>::fetch(&state, &world, e1).is_some());
3018 assert!(With::<Player>::fetch(&state, &world, e2).is_none());
3020 }
3021 }
3022
3023 mod tuple_queries {
3028 use super::*;
3029
3030 #[derive(Debug, Clone, Copy, PartialEq)]
3031 struct Position {
3032 x: f32,
3033 y: f32,
3034 }
3035 impl Component for Position {}
3036
3037 #[derive(Debug, Clone, Copy, PartialEq)]
3038 struct Velocity {
3039 x: f32,
3040 y: f32,
3041 }
3042 impl Component for Velocity {}
3043
3044 #[derive(Debug, Clone, Copy)]
3045 struct Health(f32);
3046 impl Component for Health {}
3047
3048 #[test]
3049 fn test_tuple_2_init_state() {
3050 let mut world = World::new();
3051 let state = <(&Position, &Velocity)>::init_state(&world);
3052 let (pos_id, vel_id) = state;
3053 assert_eq!(pos_id, ComponentId::of::<Position>());
3054 assert_eq!(vel_id, ComponentId::of::<Velocity>());
3055 }
3056
3057 #[test]
3058 fn test_tuple_2_component_access() {
3059 let mut world = World::new();
3060 let state = <(&Position, &Velocity)>::init_state(&world);
3061 let access = <(&Position, &Velocity)>::component_access(&state);
3062
3063 assert_eq!(access.len(), 2);
3064 assert!(access.contains(&ComponentId::of::<Position>()));
3065 assert!(access.contains(&ComponentId::of::<Velocity>()));
3066 }
3067
3068 #[test]
3069 fn test_tuple_2_fetch() {
3070 let mut world = World::new();
3071 let entity = world.spawn_empty();
3072 world.insert(entity, Position { x: 1.0, y: 2.0 });
3073 world.insert(entity, Velocity { x: 3.0, y: 4.0 });
3074
3075 let state = <(&Position, &Velocity)>::init_state(&world);
3076 let result = <(&Position, &Velocity)>::fetch(&state, &world, entity);
3077
3078 assert!(result.is_some());
3079 let (pos, vel) = result.unwrap();
3080 assert_eq!(pos.x, 1.0);
3081 assert_eq!(pos.y, 2.0);
3082 assert_eq!(vel.x, 3.0);
3083 assert_eq!(vel.y, 4.0);
3084 }
3085
3086 #[test]
3087 fn test_tuple_2_fetch_missing_component() {
3088 let mut world = World::new();
3089 let entity = world.spawn_empty();
3090 world.insert(entity, Position { x: 1.0, y: 2.0 });
3091 let state = <(&Position, &Velocity)>::init_state(&world);
3094 let result = <(&Position, &Velocity)>::fetch(&state, &world, entity);
3095
3096 assert!(result.is_none());
3097 }
3098
3099 #[test]
3100 fn test_tuple_3_fetch() {
3101 let mut world = World::new();
3102 let entity = world.spawn_empty();
3103 world.insert(entity, Position { x: 1.0, y: 2.0 });
3104 world.insert(entity, Velocity { x: 3.0, y: 4.0 });
3105 world.insert(entity, Health(100.0));
3106
3107 let state = <(&Position, &Velocity, &Health)>::init_state(&world);
3108 let result = <(&Position, &Velocity, &Health)>::fetch(&state, &world, entity);
3109
3110 assert!(result.is_some());
3111 let (pos, vel, health) = result.unwrap();
3112 assert_eq!(pos.x, 1.0);
3113 assert_eq!(vel.x, 3.0);
3114 assert_eq!(health.0, 100.0);
3115 }
3116
3117 #[test]
3118 fn test_tuple_with_entity() {
3119 let mut world = World::new();
3120 let entity = world.spawn_empty();
3121 world.insert(entity, Position { x: 1.0, y: 2.0 });
3122
3123 let state = <(Entity, &Position)>::init_state(&world);
3124 let result = <(Entity, &Position)>::fetch(&state, &world, entity);
3125
3126 assert!(result.is_some());
3127 let (e, pos) = result.unwrap();
3128 assert_eq!(e, entity);
3129 assert_eq!(pos.x, 1.0);
3130 }
3131
3132 #[test]
3133 fn test_tuple_is_read_only() {
3134 fn assert_read_only<T: ReadOnlyWorldQuery>() {}
3136 assert_read_only::<(&Position, &Velocity)>();
3137 assert_read_only::<(Entity, &Position)>();
3138 }
3139
3140 #[test]
3141 fn test_tuple_matches_archetype() {
3142 let mut world = World::new();
3143
3144 let entity = world.spawn_empty();
3146 world.insert(entity, Position { x: 1.0, y: 2.0 });
3147 world.insert(entity, Velocity { x: 3.0, y: 4.0 });
3148
3149 let archetype_id = world.entity_archetype(entity).unwrap();
3150 let archetype = world.archetypes().get(archetype_id).unwrap();
3151
3152 let state = <(&Position, &Velocity)>::init_state(&world);
3153 assert!(<(&Position, &Velocity)>::matches_archetype(
3154 &state, archetype
3155 ));
3156
3157 let entity2 = world.spawn_empty();
3159 world.insert(entity2, Position { x: 5.0, y: 6.0 });
3160
3161 let archetype_id2 = world.entity_archetype(entity2).unwrap();
3162 let archetype2 = world.archetypes().get(archetype_id2).unwrap();
3163
3164 assert!(!<(&Position, &Velocity)>::matches_archetype(
3166 &state, archetype2
3167 ));
3168 }
3169
3170 #[test]
3171 fn test_tuple_4_elements() {
3172 let mut world = World::new();
3173 let state = <(&Position, &Velocity, &Health, Entity)>::init_state(&world);
3174 let access = <(&Position, &Velocity, &Health, Entity)>::component_access(&state);
3175
3176 assert_eq!(access.len(), 3);
3178 }
3179
3180 #[test]
3181 fn test_tuple_with_filters() {
3182 let mut world = World::new();
3183 let state = <(&Position, With<Velocity>)>::init_state(&world);
3184 let access = <(&Position, With<Velocity>)>::component_access(&state);
3185
3186 assert_eq!(access.len(), 1);
3188 assert!(access.contains(&ComponentId::of::<Position>()));
3189 }
3190 }
3191}