1use crate::component::ComponentId;
2use crate::storage::SparseSetIndex;
3use crate::world::World;
4use core::{fmt, fmt::Debug, marker::PhantomData};
5use derive_more::derive::From;
6use fixedbitset::FixedBitSet;
7
8struct FormattedBitSet<'a, T: SparseSetIndex> {
26 bit_set: &'a FixedBitSet,
27 _marker: PhantomData<T>,
28}
29
30impl<'a, T: SparseSetIndex> FormattedBitSet<'a, T> {
31 fn new(bit_set: &'a FixedBitSet) -> Self {
32 Self {
33 bit_set,
34 _marker: PhantomData,
35 }
36 }
37}
38
39impl<'a, T: SparseSetIndex + Debug> Debug for FormattedBitSet<'a, T> {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 f.debug_list()
42 .entries(self.bit_set.ones().map(T::get_sparse_set_index))
43 .finish()
44 }
45}
46
47#[derive(Eq, PartialEq)]
52pub struct Access<T: SparseSetIndex> {
53 component_read_and_writes: FixedBitSet,
56 component_writes: FixedBitSet,
59 resource_read_and_writes: FixedBitSet,
61 resource_writes: FixedBitSet,
63 component_read_and_writes_inverted: bool,
66 component_writes_inverted: bool,
69 reads_all_resources: bool,
72 writes_all_resources: bool,
75 archetypal: FixedBitSet,
77 marker: PhantomData<T>,
78}
79
80impl<T: SparseSetIndex> Clone for Access<T> {
82 fn clone(&self) -> Self {
83 Self {
84 component_read_and_writes: self.component_read_and_writes.clone(),
85 component_writes: self.component_writes.clone(),
86 resource_read_and_writes: self.resource_read_and_writes.clone(),
87 resource_writes: self.resource_writes.clone(),
88 component_read_and_writes_inverted: self.component_read_and_writes_inverted,
89 component_writes_inverted: self.component_writes_inverted,
90 reads_all_resources: self.reads_all_resources,
91 writes_all_resources: self.writes_all_resources,
92 archetypal: self.archetypal.clone(),
93 marker: PhantomData,
94 }
95 }
96
97 fn clone_from(&mut self, source: &Self) {
98 self.component_read_and_writes
99 .clone_from(&source.component_read_and_writes);
100 self.component_writes.clone_from(&source.component_writes);
101 self.resource_read_and_writes
102 .clone_from(&source.resource_read_and_writes);
103 self.resource_writes.clone_from(&source.resource_writes);
104 self.component_read_and_writes_inverted = source.component_read_and_writes_inverted;
105 self.component_writes_inverted = source.component_writes_inverted;
106 self.reads_all_resources = source.reads_all_resources;
107 self.writes_all_resources = source.writes_all_resources;
108 self.archetypal.clone_from(&source.archetypal);
109 }
110}
111
112impl<T: SparseSetIndex + Debug> Debug for Access<T> {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 f.debug_struct("Access")
115 .field(
116 "component_read_and_writes",
117 &FormattedBitSet::<T>::new(&self.component_read_and_writes),
118 )
119 .field(
120 "component_writes",
121 &FormattedBitSet::<T>::new(&self.component_writes),
122 )
123 .field(
124 "resource_read_and_writes",
125 &FormattedBitSet::<T>::new(&self.resource_read_and_writes),
126 )
127 .field(
128 "resource_writes",
129 &FormattedBitSet::<T>::new(&self.resource_writes),
130 )
131 .field(
132 "component_read_and_writes_inverted",
133 &self.component_read_and_writes_inverted,
134 )
135 .field("component_writes_inverted", &self.component_writes_inverted)
136 .field("reads_all_resources", &self.reads_all_resources)
137 .field("writes_all_resources", &self.writes_all_resources)
138 .field("archetypal", &FormattedBitSet::<T>::new(&self.archetypal))
139 .finish()
140 }
141}
142
143impl<T: SparseSetIndex> Default for Access<T> {
144 fn default() -> Self {
145 Self::new()
146 }
147}
148
149impl<T: SparseSetIndex> Access<T> {
150 pub const fn new() -> Self {
152 Self {
153 reads_all_resources: false,
154 writes_all_resources: false,
155 component_read_and_writes_inverted: false,
156 component_writes_inverted: false,
157 component_read_and_writes: FixedBitSet::new(),
158 component_writes: FixedBitSet::new(),
159 resource_read_and_writes: FixedBitSet::new(),
160 resource_writes: FixedBitSet::new(),
161 archetypal: FixedBitSet::new(),
162 marker: PhantomData,
163 }
164 }
165
166 fn add_component_sparse_set_index_read(&mut self, index: usize) {
167 if !self.component_read_and_writes_inverted {
168 self.component_read_and_writes.grow_and_insert(index);
169 } else if index < self.component_read_and_writes.len() {
170 self.component_read_and_writes.remove(index);
171 }
172 }
173
174 fn add_component_sparse_set_index_write(&mut self, index: usize) {
175 if !self.component_writes_inverted {
176 self.component_writes.grow_and_insert(index);
177 } else if index < self.component_writes.len() {
178 self.component_writes.remove(index);
179 }
180 }
181
182 pub fn add_component_read(&mut self, index: T) {
184 let sparse_set_index = index.sparse_set_index();
185 self.add_component_sparse_set_index_read(sparse_set_index);
186 }
187
188 pub fn add_component_write(&mut self, index: T) {
190 let sparse_set_index = index.sparse_set_index();
191 self.add_component_sparse_set_index_read(sparse_set_index);
192 self.add_component_sparse_set_index_write(sparse_set_index);
193 }
194
195 pub fn add_resource_read(&mut self, index: T) {
197 self.resource_read_and_writes
198 .grow_and_insert(index.sparse_set_index());
199 }
200
201 pub fn add_resource_write(&mut self, index: T) {
203 self.resource_read_and_writes
204 .grow_and_insert(index.sparse_set_index());
205 self.resource_writes
206 .grow_and_insert(index.sparse_set_index());
207 }
208
209 fn remove_component_sparse_set_index_read(&mut self, index: usize) {
210 if self.component_read_and_writes_inverted {
211 self.component_read_and_writes.grow_and_insert(index);
212 } else if index < self.component_read_and_writes.len() {
213 self.component_read_and_writes.remove(index);
214 }
215 }
216
217 fn remove_component_sparse_set_index_write(&mut self, index: usize) {
218 if self.component_writes_inverted {
219 self.component_writes.grow_and_insert(index);
220 } else if index < self.component_writes.len() {
221 self.component_writes.remove(index);
222 }
223 }
224
225 pub fn remove_component_read(&mut self, index: T) {
234 let sparse_set_index = index.sparse_set_index();
235 self.remove_component_sparse_set_index_write(sparse_set_index);
236 self.remove_component_sparse_set_index_read(sparse_set_index);
237 }
238
239 pub fn remove_component_write(&mut self, index: T) {
248 let sparse_set_index = index.sparse_set_index();
249 self.remove_component_sparse_set_index_write(sparse_set_index);
250 }
251
252 pub fn add_archetypal(&mut self, index: T) {
261 self.archetypal.grow_and_insert(index.sparse_set_index());
262 }
263
264 pub fn has_component_read(&self, index: T) -> bool {
266 self.component_read_and_writes_inverted
267 ^ self
268 .component_read_and_writes
269 .contains(index.sparse_set_index())
270 }
271
272 pub fn has_any_component_read(&self) -> bool {
274 self.component_read_and_writes_inverted || !self.component_read_and_writes.is_clear()
275 }
276
277 pub fn has_component_write(&self, index: T) -> bool {
279 self.component_writes_inverted ^ self.component_writes.contains(index.sparse_set_index())
280 }
281
282 pub fn has_any_component_write(&self) -> bool {
284 self.component_writes_inverted || !self.component_writes.is_clear()
285 }
286
287 pub fn has_resource_read(&self, index: T) -> bool {
289 self.reads_all_resources
290 || self
291 .resource_read_and_writes
292 .contains(index.sparse_set_index())
293 }
294
295 pub fn has_any_resource_read(&self) -> bool {
297 self.reads_all_resources || !self.resource_read_and_writes.is_clear()
298 }
299
300 pub fn has_resource_write(&self, index: T) -> bool {
302 self.writes_all_resources || self.resource_writes.contains(index.sparse_set_index())
303 }
304
305 pub fn has_any_resource_write(&self) -> bool {
307 self.writes_all_resources || !self.resource_writes.is_clear()
308 }
309
310 pub fn has_archetypal(&self, index: T) -> bool {
319 self.archetypal.contains(index.sparse_set_index())
320 }
321
322 #[inline]
324 pub fn read_all_components(&mut self) {
325 self.component_read_and_writes_inverted = true;
326 self.component_read_and_writes.clear();
327 }
328
329 #[inline]
331 pub fn write_all_components(&mut self) {
332 self.read_all_components();
333 self.component_writes_inverted = true;
334 self.component_writes.clear();
335 }
336
337 #[inline]
339 pub fn read_all_resources(&mut self) {
340 self.reads_all_resources = true;
341 }
342
343 #[inline]
345 pub fn write_all_resources(&mut self) {
346 self.reads_all_resources = true;
347 self.writes_all_resources = true;
348 }
349
350 #[inline]
352 pub fn read_all(&mut self) {
353 self.read_all_components();
354 self.read_all_resources();
355 }
356
357 #[inline]
359 pub fn write_all(&mut self) {
360 self.write_all_components();
361 self.write_all_resources();
362 }
363
364 #[inline]
366 pub fn has_read_all_components(&self) -> bool {
367 self.component_read_and_writes_inverted && self.component_read_and_writes.is_clear()
368 }
369
370 #[inline]
372 pub fn has_write_all_components(&self) -> bool {
373 self.component_writes_inverted && self.component_writes.is_clear()
374 }
375
376 #[inline]
378 pub fn has_read_all_resources(&self) -> bool {
379 self.reads_all_resources
380 }
381
382 #[inline]
384 pub fn has_write_all_resources(&self) -> bool {
385 self.writes_all_resources
386 }
387
388 pub fn has_read_all(&self) -> bool {
390 self.has_read_all_components() && self.has_read_all_resources()
391 }
392
393 pub fn has_write_all(&self) -> bool {
395 self.has_write_all_components() && self.has_write_all_resources()
396 }
397
398 pub fn clear_writes(&mut self) {
400 self.writes_all_resources = false;
401 self.component_writes_inverted = false;
402 self.component_writes.clear();
403 self.resource_writes.clear();
404 }
405
406 pub fn clear(&mut self) {
408 self.reads_all_resources = false;
409 self.writes_all_resources = false;
410 self.component_read_and_writes_inverted = false;
411 self.component_writes_inverted = false;
412 self.component_read_and_writes.clear();
413 self.component_writes.clear();
414 self.resource_read_and_writes.clear();
415 self.resource_writes.clear();
416 }
417
418 pub fn extend(&mut self, other: &Access<T>) {
420 let component_read_and_writes_inverted =
421 self.component_read_and_writes_inverted || other.component_read_and_writes_inverted;
422 let component_writes_inverted =
423 self.component_writes_inverted || other.component_writes_inverted;
424
425 match (
426 self.component_read_and_writes_inverted,
427 other.component_read_and_writes_inverted,
428 ) {
429 (true, true) => {
430 self.component_read_and_writes
431 .intersect_with(&other.component_read_and_writes);
432 }
433 (true, false) => {
434 self.component_read_and_writes
435 .difference_with(&other.component_read_and_writes);
436 }
437 (false, true) => {
438 self.component_read_and_writes.grow(
440 self.component_read_and_writes
441 .len()
442 .max(other.component_read_and_writes.len()),
443 );
444 self.component_read_and_writes.toggle_range(..);
445 self.component_read_and_writes
446 .intersect_with(&other.component_read_and_writes);
447 }
448 (false, false) => {
449 self.component_read_and_writes
450 .union_with(&other.component_read_and_writes);
451 }
452 }
453
454 match (
455 self.component_writes_inverted,
456 other.component_writes_inverted,
457 ) {
458 (true, true) => {
459 self.component_writes
460 .intersect_with(&other.component_writes);
461 }
462 (true, false) => {
463 self.component_writes
464 .difference_with(&other.component_writes);
465 }
466 (false, true) => {
467 self.component_writes.grow(
469 self.component_writes
470 .len()
471 .max(other.component_writes.len()),
472 );
473 self.component_writes.toggle_range(..);
474 self.component_writes
475 .intersect_with(&other.component_writes);
476 }
477 (false, false) => {
478 self.component_writes.union_with(&other.component_writes);
479 }
480 }
481
482 self.reads_all_resources = self.reads_all_resources || other.reads_all_resources;
483 self.writes_all_resources = self.writes_all_resources || other.writes_all_resources;
484 self.component_read_and_writes_inverted = component_read_and_writes_inverted;
485 self.component_writes_inverted = component_writes_inverted;
486 self.resource_read_and_writes
487 .union_with(&other.resource_read_and_writes);
488 self.resource_writes.union_with(&other.resource_writes);
489 }
490
491 pub fn is_components_compatible(&self, other: &Access<T>) -> bool {
497 for (
500 lhs_writes,
501 rhs_reads_and_writes,
502 lhs_writes_inverted,
503 rhs_reads_and_writes_inverted,
504 ) in [
505 (
506 &self.component_writes,
507 &other.component_read_and_writes,
508 self.component_writes_inverted,
509 other.component_read_and_writes_inverted,
510 ),
511 (
512 &other.component_writes,
513 &self.component_read_and_writes,
514 other.component_writes_inverted,
515 self.component_read_and_writes_inverted,
516 ),
517 ] {
518 match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
519 (true, true) => return false,
520 (false, true) => {
521 if !lhs_writes.is_subset(rhs_reads_and_writes) {
522 return false;
523 }
524 }
525 (true, false) => {
526 if !rhs_reads_and_writes.is_subset(lhs_writes) {
527 return false;
528 }
529 }
530 (false, false) => {
531 if !lhs_writes.is_disjoint(rhs_reads_and_writes) {
532 return false;
533 }
534 }
535 }
536 }
537
538 true
539 }
540
541 pub fn is_resources_compatible(&self, other: &Access<T>) -> bool {
547 if self.writes_all_resources {
548 return !other.has_any_resource_read();
549 }
550
551 if other.writes_all_resources {
552 return !self.has_any_resource_read();
553 }
554
555 if self.reads_all_resources {
556 return !other.has_any_resource_write();
557 }
558
559 if other.reads_all_resources {
560 return !self.has_any_resource_write();
561 }
562
563 self.resource_writes
564 .is_disjoint(&other.resource_read_and_writes)
565 && other
566 .resource_writes
567 .is_disjoint(&self.resource_read_and_writes)
568 }
569
570 pub fn is_compatible(&self, other: &Access<T>) -> bool {
575 self.is_components_compatible(other) && self.is_resources_compatible(other)
576 }
577
578 pub fn is_subset_components(&self, other: &Access<T>) -> bool {
581 for (
582 our_components,
583 their_components,
584 our_components_inverted,
585 their_components_inverted,
586 ) in [
587 (
588 &self.component_read_and_writes,
589 &other.component_read_and_writes,
590 self.component_read_and_writes_inverted,
591 other.component_read_and_writes_inverted,
592 ),
593 (
594 &self.component_writes,
595 &other.component_writes,
596 self.component_writes_inverted,
597 other.component_writes_inverted,
598 ),
599 ] {
600 match (our_components_inverted, their_components_inverted) {
601 (true, true) => {
602 if !their_components.is_subset(our_components) {
603 return false;
604 }
605 }
606 (true, false) => {
607 return false;
608 }
609 (false, true) => {
610 if !our_components.is_disjoint(their_components) {
611 return false;
612 }
613 }
614 (false, false) => {
615 if !our_components.is_subset(their_components) {
616 return false;
617 }
618 }
619 }
620 }
621
622 true
623 }
624
625 pub fn is_subset_resources(&self, other: &Access<T>) -> bool {
628 if self.writes_all_resources {
629 return other.writes_all_resources;
630 }
631
632 if other.writes_all_resources {
633 return true;
634 }
635
636 if self.reads_all_resources {
637 return other.reads_all_resources;
638 }
639
640 if other.reads_all_resources {
641 return self.resource_writes.is_subset(&other.resource_writes);
642 }
643
644 self.resource_read_and_writes
645 .is_subset(&other.resource_read_and_writes)
646 && self.resource_writes.is_subset(&other.resource_writes)
647 }
648
649 pub fn is_subset(&self, other: &Access<T>) -> bool {
652 self.is_subset_components(other) && self.is_subset_resources(other)
653 }
654
655 fn get_component_conflicts(&self, other: &Access<T>) -> AccessConflicts {
656 let mut conflicts = FixedBitSet::new();
657
658 for (
661 lhs_writes,
662 rhs_reads_and_writes,
663 lhs_writes_inverted,
664 rhs_reads_and_writes_inverted,
665 ) in [
666 (
667 &self.component_writes,
668 &other.component_read_and_writes,
669 self.component_writes_inverted,
670 other.component_read_and_writes_inverted,
671 ),
672 (
673 &other.component_writes,
674 &self.component_read_and_writes,
675 other.component_writes_inverted,
676 self.component_read_and_writes_inverted,
677 ),
678 ] {
679 let temp_conflicts: FixedBitSet =
682 match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
683 (true, true) => return AccessConflicts::All,
684 (false, true) => lhs_writes.difference(rhs_reads_and_writes).collect(),
685 (true, false) => rhs_reads_and_writes.difference(lhs_writes).collect(),
686 (false, false) => lhs_writes.intersection(rhs_reads_and_writes).collect(),
687 };
688 conflicts.union_with(&temp_conflicts);
689 }
690
691 AccessConflicts::Individual(conflicts)
692 }
693
694 pub fn get_conflicts(&self, other: &Access<T>) -> AccessConflicts {
696 let mut conflicts = match self.get_component_conflicts(other) {
697 AccessConflicts::All => return AccessConflicts::All,
698 AccessConflicts::Individual(conflicts) => conflicts,
699 };
700
701 if self.reads_all_resources {
702 if other.writes_all_resources {
703 return AccessConflicts::All;
704 }
705 conflicts.extend(other.resource_writes.ones());
706 }
707
708 if other.reads_all_resources {
709 if self.writes_all_resources {
710 return AccessConflicts::All;
711 }
712 conflicts.extend(self.resource_writes.ones());
713 }
714 if self.writes_all_resources {
715 conflicts.extend(other.resource_read_and_writes.ones());
716 }
717
718 if other.writes_all_resources {
719 conflicts.extend(self.resource_read_and_writes.ones());
720 }
721
722 conflicts.extend(
723 self.resource_writes
724 .intersection(&other.resource_read_and_writes),
725 );
726 conflicts.extend(
727 self.resource_read_and_writes
728 .intersection(&other.resource_writes),
729 );
730 AccessConflicts::Individual(conflicts)
731 }
732
733 pub fn resource_reads_and_writes(&self) -> impl Iterator<Item = T> + '_ {
735 self.resource_read_and_writes
736 .ones()
737 .map(T::get_sparse_set_index)
738 }
739
740 pub fn resource_reads(&self) -> impl Iterator<Item = T> + '_ {
742 self.resource_read_and_writes
743 .difference(&self.resource_writes)
744 .map(T::get_sparse_set_index)
745 }
746
747 pub fn resource_writes(&self) -> impl Iterator<Item = T> + '_ {
749 self.resource_writes.ones().map(T::get_sparse_set_index)
750 }
751
752 pub fn archetypal(&self) -> impl Iterator<Item = T> + '_ {
761 self.archetypal.ones().map(T::get_sparse_set_index)
762 }
763
764 #[doc(hidden)]
775 pub fn component_reads_and_writes(&self) -> (impl Iterator<Item = T> + '_, bool) {
777 (
778 self.component_read_and_writes
779 .ones()
780 .map(T::get_sparse_set_index),
781 self.component_read_and_writes_inverted,
782 )
783 }
784
785 pub(crate) fn component_writes(&self) -> (impl Iterator<Item = T> + '_, bool) {
792 (
793 self.component_writes.ones().map(T::get_sparse_set_index),
794 self.component_writes_inverted,
795 )
796 }
797}
798
799#[derive(Debug, Eq, PartialEq)]
820pub struct FilteredAccess<T: SparseSetIndex> {
821 pub(crate) access: Access<T>,
822 pub(crate) required: FixedBitSet,
823 pub(crate) filter_sets: Vec<AccessFilters<T>>,
826}
827
828impl<T: SparseSetIndex> Clone for FilteredAccess<T> {
830 fn clone(&self) -> Self {
831 Self {
832 access: self.access.clone(),
833 required: self.required.clone(),
834 filter_sets: self.filter_sets.clone(),
835 }
836 }
837
838 fn clone_from(&mut self, source: &Self) {
839 self.access.clone_from(&source.access);
840 self.required.clone_from(&source.required);
841 self.filter_sets.clone_from(&source.filter_sets);
842 }
843}
844
845impl<T: SparseSetIndex> Default for FilteredAccess<T> {
846 fn default() -> Self {
847 Self::matches_everything()
848 }
849}
850
851impl<T: SparseSetIndex> From<FilteredAccess<T>> for FilteredAccessSet<T> {
852 fn from(filtered_access: FilteredAccess<T>) -> Self {
853 let mut base = FilteredAccessSet::<T>::default();
854 base.add(filtered_access);
855 base
856 }
857}
858
859#[derive(Debug, PartialEq, From)]
861pub enum AccessConflicts {
862 All,
864 Individual(FixedBitSet),
866}
867
868impl AccessConflicts {
869 fn add(&mut self, other: &Self) {
870 match (self, other) {
871 (s, AccessConflicts::All) => {
872 *s = AccessConflicts::All;
873 }
874 (AccessConflicts::Individual(this), AccessConflicts::Individual(other)) => {
875 this.extend(other.ones());
876 }
877 _ => {}
878 }
879 }
880
881 pub(crate) fn is_empty(&self) -> bool {
882 match self {
883 Self::All => false,
884 Self::Individual(set) => set.is_empty(),
885 }
886 }
887
888 pub(crate) fn format_conflict_list(&self, world: &World) -> String {
889 match self {
890 AccessConflicts::All => String::new(),
891 AccessConflicts::Individual(indices) => format!(
892 " {}",
893 indices
894 .ones()
895 .map(|index| world
896 .components
897 .get_info(ComponentId::get_sparse_set_index(index))
898 .unwrap()
899 .name())
900 .collect::<Vec<&str>>()
901 .join(", ")
902 ),
903 }
904 }
905
906 pub(crate) fn empty() -> Self {
908 Self::Individual(FixedBitSet::new())
909 }
910}
911
912impl<T: SparseSetIndex> From<Vec<T>> for AccessConflicts {
913 fn from(value: Vec<T>) -> Self {
914 Self::Individual(value.iter().map(T::sparse_set_index).collect())
915 }
916}
917
918impl<T: SparseSetIndex> FilteredAccess<T> {
919 pub fn matches_everything() -> Self {
922 Self {
923 access: Access::default(),
924 required: FixedBitSet::default(),
925 filter_sets: vec![AccessFilters::default()],
926 }
927 }
928
929 pub fn matches_nothing() -> Self {
932 Self {
933 access: Access::default(),
934 required: FixedBitSet::default(),
935 filter_sets: Vec::new(),
936 }
937 }
938
939 #[inline]
941 pub fn access(&self) -> &Access<T> {
942 &self.access
943 }
944
945 #[inline]
947 pub fn access_mut(&mut self) -> &mut Access<T> {
948 &mut self.access
949 }
950
951 pub fn add_component_read(&mut self, index: T) {
953 self.access.add_component_read(index.clone());
954 self.add_required(index.clone());
955 self.and_with(index);
956 }
957
958 pub fn add_component_write(&mut self, index: T) {
960 self.access.add_component_write(index.clone());
961 self.add_required(index.clone());
962 self.and_with(index);
963 }
964
965 pub fn add_resource_read(&mut self, index: T) {
967 self.access.add_resource_read(index.clone());
968 }
969
970 pub fn add_resource_write(&mut self, index: T) {
972 self.access.add_resource_write(index.clone());
973 }
974
975 fn add_required(&mut self, index: T) {
976 self.required.grow_and_insert(index.sparse_set_index());
977 }
978
979 pub fn and_with(&mut self, index: T) {
984 for filter in &mut self.filter_sets {
985 filter.with.grow_and_insert(index.sparse_set_index());
986 }
987 }
988
989 pub fn and_without(&mut self, index: T) {
994 for filter in &mut self.filter_sets {
995 filter.without.grow_and_insert(index.sparse_set_index());
996 }
997 }
998
999 pub fn append_or(&mut self, other: &FilteredAccess<T>) {
1005 self.filter_sets.append(&mut other.filter_sets.clone());
1006 }
1007
1008 pub fn extend_access(&mut self, other: &FilteredAccess<T>) {
1010 self.access.extend(&other.access);
1011 }
1012
1013 pub fn is_compatible(&self, other: &FilteredAccess<T>) -> bool {
1015 if self.access.is_compatible(&other.access) {
1016 return true;
1017 }
1018
1019 self.filter_sets.iter().all(|filter| {
1027 other
1028 .filter_sets
1029 .iter()
1030 .all(|other_filter| filter.is_ruled_out_by(other_filter))
1031 })
1032 }
1033
1034 pub fn get_conflicts(&self, other: &FilteredAccess<T>) -> AccessConflicts {
1036 if !self.is_compatible(other) {
1037 return self.access.get_conflicts(&other.access);
1039 }
1040 AccessConflicts::empty()
1041 }
1042
1043 pub fn extend(&mut self, other: &FilteredAccess<T>) {
1050 self.access.extend(&other.access);
1051 self.required.union_with(&other.required);
1052
1053 if other.filter_sets.len() == 1 {
1056 for filter in &mut self.filter_sets {
1057 filter.with.union_with(&other.filter_sets[0].with);
1058 filter.without.union_with(&other.filter_sets[0].without);
1059 }
1060 return;
1061 }
1062
1063 let mut new_filters = Vec::with_capacity(self.filter_sets.len() * other.filter_sets.len());
1064 for filter in &self.filter_sets {
1065 for other_filter in &other.filter_sets {
1066 let mut new_filter = filter.clone();
1067 new_filter.with.union_with(&other_filter.with);
1068 new_filter.without.union_with(&other_filter.without);
1069 new_filters.push(new_filter);
1070 }
1071 }
1072 self.filter_sets = new_filters;
1073 }
1074
1075 pub fn read_all(&mut self) {
1077 self.access.read_all();
1078 }
1079
1080 pub fn write_all(&mut self) {
1082 self.access.write_all();
1083 }
1084
1085 pub fn read_all_components(&mut self) {
1087 self.access.read_all_components();
1088 }
1089
1090 pub fn write_all_components(&mut self) {
1092 self.access.write_all_components();
1093 }
1094
1095 pub fn is_subset(&self, other: &FilteredAccess<T>) -> bool {
1098 self.required.is_subset(&other.required) && self.access().is_subset(other.access())
1099 }
1100
1101 pub fn with_filters(&self) -> impl Iterator<Item = T> + '_ {
1103 self.filter_sets
1104 .iter()
1105 .flat_map(|f| f.with.ones().map(T::get_sparse_set_index))
1106 }
1107
1108 pub fn without_filters(&self) -> impl Iterator<Item = T> + '_ {
1110 self.filter_sets
1111 .iter()
1112 .flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
1113 }
1114}
1115
1116#[derive(Eq, PartialEq)]
1117pub(crate) struct AccessFilters<T> {
1118 pub(crate) with: FixedBitSet,
1119 pub(crate) without: FixedBitSet,
1120 _index_type: PhantomData<T>,
1121}
1122
1123impl<T: SparseSetIndex> Clone for AccessFilters<T> {
1125 fn clone(&self) -> Self {
1126 Self {
1127 with: self.with.clone(),
1128 without: self.without.clone(),
1129 _index_type: PhantomData,
1130 }
1131 }
1132
1133 fn clone_from(&mut self, source: &Self) {
1134 self.with.clone_from(&source.with);
1135 self.without.clone_from(&source.without);
1136 }
1137}
1138
1139impl<T: SparseSetIndex + Debug> Debug for AccessFilters<T> {
1140 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141 f.debug_struct("AccessFilters")
1142 .field("with", &FormattedBitSet::<T>::new(&self.with))
1143 .field("without", &FormattedBitSet::<T>::new(&self.without))
1144 .finish()
1145 }
1146}
1147
1148impl<T: SparseSetIndex> Default for AccessFilters<T> {
1149 fn default() -> Self {
1150 Self {
1151 with: FixedBitSet::default(),
1152 without: FixedBitSet::default(),
1153 _index_type: PhantomData,
1154 }
1155 }
1156}
1157
1158impl<T: SparseSetIndex> AccessFilters<T> {
1159 fn is_ruled_out_by(&self, other: &Self) -> bool {
1160 !self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
1166 }
1167}
1168
1169#[derive(Debug, PartialEq, Eq)]
1177pub struct FilteredAccessSet<T: SparseSetIndex> {
1178 combined_access: Access<T>,
1179 filtered_accesses: Vec<FilteredAccess<T>>,
1180}
1181
1182impl<T: SparseSetIndex> Clone for FilteredAccessSet<T> {
1184 fn clone(&self) -> Self {
1185 Self {
1186 combined_access: self.combined_access.clone(),
1187 filtered_accesses: self.filtered_accesses.clone(),
1188 }
1189 }
1190
1191 fn clone_from(&mut self, source: &Self) {
1192 self.combined_access.clone_from(&source.combined_access);
1193 self.filtered_accesses.clone_from(&source.filtered_accesses);
1194 }
1195}
1196
1197impl<T: SparseSetIndex> FilteredAccessSet<T> {
1198 #[inline]
1200 pub fn combined_access(&self) -> &Access<T> {
1201 &self.combined_access
1202 }
1203
1204 pub fn is_compatible(&self, other: &FilteredAccessSet<T>) -> bool {
1217 if self.combined_access.is_compatible(other.combined_access()) {
1218 return true;
1219 }
1220 for filtered in &self.filtered_accesses {
1221 for other_filtered in &other.filtered_accesses {
1222 if !filtered.is_compatible(other_filtered) {
1223 return false;
1224 }
1225 }
1226 }
1227 true
1228 }
1229
1230 pub fn get_conflicts(&self, other: &FilteredAccessSet<T>) -> AccessConflicts {
1232 let mut conflicts = AccessConflicts::empty();
1234 if !self.combined_access.is_compatible(other.combined_access()) {
1235 for filtered in &self.filtered_accesses {
1236 for other_filtered in &other.filtered_accesses {
1237 conflicts.add(&filtered.get_conflicts(other_filtered));
1238 }
1239 }
1240 }
1241 conflicts
1242 }
1243
1244 pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess<T>) -> AccessConflicts {
1246 let mut conflicts = AccessConflicts::empty();
1248 if !self.combined_access.is_compatible(filtered_access.access()) {
1249 for filtered in &self.filtered_accesses {
1250 conflicts.add(&filtered.get_conflicts(filtered_access));
1251 }
1252 }
1253 conflicts
1254 }
1255
1256 pub fn add(&mut self, filtered_access: FilteredAccess<T>) {
1258 self.combined_access.extend(&filtered_access.access);
1259 self.filtered_accesses.push(filtered_access);
1260 }
1261
1262 pub(crate) fn add_unfiltered_resource_read(&mut self, index: T) {
1264 let mut filter = FilteredAccess::default();
1265 filter.add_resource_read(index);
1266 self.add(filter);
1267 }
1268
1269 pub(crate) fn add_unfiltered_resource_write(&mut self, index: T) {
1271 let mut filter = FilteredAccess::default();
1272 filter.add_resource_write(index);
1273 self.add(filter);
1274 }
1275
1276 pub(crate) fn add_unfiltered_read_all_resources(&mut self) {
1278 let mut filter = FilteredAccess::default();
1279 filter.access.read_all_resources();
1280 self.add(filter);
1281 }
1282
1283 pub(crate) fn add_unfiltered_write_all_resources(&mut self) {
1285 let mut filter = FilteredAccess::default();
1286 filter.access.write_all_resources();
1287 self.add(filter);
1288 }
1289
1290 pub fn extend(&mut self, filtered_access_set: FilteredAccessSet<T>) {
1292 self.combined_access
1293 .extend(&filtered_access_set.combined_access);
1294 self.filtered_accesses
1295 .extend(filtered_access_set.filtered_accesses);
1296 }
1297
1298 pub fn read_all(&mut self) {
1300 self.combined_access.read_all();
1301 }
1302
1303 pub fn write_all(&mut self) {
1305 self.combined_access.write_all();
1306 }
1307
1308 pub fn clear(&mut self) {
1310 self.combined_access.clear();
1311 self.filtered_accesses.clear();
1312 }
1313}
1314
1315impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
1316 fn default() -> Self {
1317 Self {
1318 combined_access: Default::default(),
1319 filtered_accesses: Vec::new(),
1320 }
1321 }
1322}
1323
1324#[cfg(test)]
1325mod tests {
1326 use crate::query::{
1327 access::AccessFilters, Access, AccessConflicts, FilteredAccess, FilteredAccessSet,
1328 };
1329 use core::marker::PhantomData;
1330 use fixedbitset::FixedBitSet;
1331
1332 fn create_sample_access() -> Access<usize> {
1333 let mut access = Access::<usize>::default();
1334
1335 access.add_component_read(1);
1336 access.add_component_read(2);
1337 access.add_component_write(3);
1338 access.add_archetypal(5);
1339 access.read_all();
1340
1341 access
1342 }
1343
1344 fn create_sample_filtered_access() -> FilteredAccess<usize> {
1345 let mut filtered_access = FilteredAccess::<usize>::default();
1346
1347 filtered_access.add_component_write(1);
1348 filtered_access.add_component_read(2);
1349 filtered_access.add_required(3);
1350 filtered_access.and_with(4);
1351
1352 filtered_access
1353 }
1354
1355 fn create_sample_access_filters() -> AccessFilters<usize> {
1356 let mut access_filters = AccessFilters::<usize>::default();
1357
1358 access_filters.with.grow_and_insert(3);
1359 access_filters.without.grow_and_insert(5);
1360
1361 access_filters
1362 }
1363
1364 fn create_sample_filtered_access_set() -> FilteredAccessSet<usize> {
1365 let mut filtered_access_set = FilteredAccessSet::<usize>::default();
1366
1367 filtered_access_set.add_unfiltered_resource_read(2);
1368 filtered_access_set.add_unfiltered_resource_write(4);
1369 filtered_access_set.read_all();
1370
1371 filtered_access_set
1372 }
1373
1374 #[test]
1375 fn test_access_clone() {
1376 let original: Access<usize> = create_sample_access();
1377 let cloned = original.clone();
1378
1379 assert_eq!(original, cloned);
1380 }
1381
1382 #[test]
1383 fn test_access_clone_from() {
1384 let original: Access<usize> = create_sample_access();
1385 let mut cloned = Access::<usize>::default();
1386
1387 cloned.add_component_write(7);
1388 cloned.add_component_read(4);
1389 cloned.add_archetypal(8);
1390 cloned.write_all();
1391
1392 cloned.clone_from(&original);
1393
1394 assert_eq!(original, cloned);
1395 }
1396
1397 #[test]
1398 fn test_filtered_access_clone() {
1399 let original: FilteredAccess<usize> = create_sample_filtered_access();
1400 let cloned = original.clone();
1401
1402 assert_eq!(original, cloned);
1403 }
1404
1405 #[test]
1406 fn test_filtered_access_clone_from() {
1407 let original: FilteredAccess<usize> = create_sample_filtered_access();
1408 let mut cloned = FilteredAccess::<usize>::default();
1409
1410 cloned.add_component_write(7);
1411 cloned.add_component_read(4);
1412 cloned.append_or(&FilteredAccess::default());
1413
1414 cloned.clone_from(&original);
1415
1416 assert_eq!(original, cloned);
1417 }
1418
1419 #[test]
1420 fn test_access_filters_clone() {
1421 let original: AccessFilters<usize> = create_sample_access_filters();
1422 let cloned = original.clone();
1423
1424 assert_eq!(original, cloned);
1425 }
1426
1427 #[test]
1428 fn test_access_filters_clone_from() {
1429 let original: AccessFilters<usize> = create_sample_access_filters();
1430 let mut cloned = AccessFilters::<usize>::default();
1431
1432 cloned.with.grow_and_insert(1);
1433 cloned.without.grow_and_insert(2);
1434
1435 cloned.clone_from(&original);
1436
1437 assert_eq!(original, cloned);
1438 }
1439
1440 #[test]
1441 fn test_filtered_access_set_clone() {
1442 let original: FilteredAccessSet<usize> = create_sample_filtered_access_set();
1443 let cloned = original.clone();
1444
1445 assert_eq!(original, cloned);
1446 }
1447
1448 #[test]
1449 fn test_filtered_access_set_from() {
1450 let original: FilteredAccessSet<usize> = create_sample_filtered_access_set();
1451 let mut cloned = FilteredAccessSet::<usize>::default();
1452
1453 cloned.add_unfiltered_resource_read(7);
1454 cloned.add_unfiltered_resource_write(9);
1455 cloned.write_all();
1456
1457 cloned.clone_from(&original);
1458
1459 assert_eq!(original, cloned);
1460 }
1461
1462 #[test]
1463 fn read_all_access_conflicts() {
1464 let mut access_a = Access::<usize>::default();
1466 access_a.add_component_write(0);
1467
1468 let mut access_b = Access::<usize>::default();
1469 access_b.read_all();
1470
1471 assert!(!access_b.is_compatible(&access_a));
1472
1473 let mut access_a = Access::<usize>::default();
1475 access_a.read_all();
1476
1477 let mut access_b = Access::<usize>::default();
1478 access_b.read_all();
1479
1480 assert!(access_b.is_compatible(&access_a));
1481 }
1482
1483 #[test]
1484 fn access_get_conflicts() {
1485 let mut access_a = Access::<usize>::default();
1486 access_a.add_component_read(0);
1487 access_a.add_component_read(1);
1488
1489 let mut access_b = Access::<usize>::default();
1490 access_b.add_component_read(0);
1491 access_b.add_component_write(1);
1492
1493 assert_eq!(access_a.get_conflicts(&access_b), vec![1_usize].into());
1494
1495 let mut access_c = Access::<usize>::default();
1496 access_c.add_component_write(0);
1497 access_c.add_component_write(1);
1498
1499 assert_eq!(
1500 access_a.get_conflicts(&access_c),
1501 vec![0_usize, 1_usize].into()
1502 );
1503 assert_eq!(
1504 access_b.get_conflicts(&access_c),
1505 vec![0_usize, 1_usize].into()
1506 );
1507
1508 let mut access_d = Access::<usize>::default();
1509 access_d.add_component_read(0);
1510
1511 assert_eq!(access_d.get_conflicts(&access_a), AccessConflicts::empty());
1512 assert_eq!(access_d.get_conflicts(&access_b), AccessConflicts::empty());
1513 assert_eq!(access_d.get_conflicts(&access_c), vec![0_usize].into());
1514 }
1515
1516 #[test]
1517 fn filtered_combined_access() {
1518 let mut access_a = FilteredAccessSet::<usize>::default();
1519 access_a.add_unfiltered_resource_read(1);
1520
1521 let mut filter_b = FilteredAccess::<usize>::default();
1522 filter_b.add_resource_write(1);
1523
1524 let conflicts = access_a.get_conflicts_single(&filter_b);
1525 assert_eq!(
1526 &conflicts,
1527 &AccessConflicts::from(vec![1_usize]),
1528 "access_a: {access_a:?}, filter_b: {filter_b:?}"
1529 );
1530 }
1531
1532 #[test]
1533 fn filtered_access_extend() {
1534 let mut access_a = FilteredAccess::<usize>::default();
1535 access_a.add_component_read(0);
1536 access_a.add_component_read(1);
1537 access_a.and_with(2);
1538
1539 let mut access_b = FilteredAccess::<usize>::default();
1540 access_b.add_component_read(0);
1541 access_b.add_component_write(3);
1542 access_b.and_without(4);
1543
1544 access_a.extend(&access_b);
1545
1546 let mut expected = FilteredAccess::<usize>::default();
1547 expected.add_component_read(0);
1548 expected.add_component_read(1);
1549 expected.and_with(2);
1550 expected.add_component_write(3);
1551 expected.and_without(4);
1552
1553 assert!(access_a.eq(&expected));
1554 }
1555
1556 #[test]
1557 fn filtered_access_extend_or() {
1558 let mut access_a = FilteredAccess::<usize>::default();
1559 access_a.add_component_write(0);
1561 access_a.add_component_write(1);
1562
1563 let mut access_b = FilteredAccess::<usize>::default();
1565 access_b.and_with(2);
1566
1567 let mut access_c = FilteredAccess::<usize>::default();
1569 access_c.and_with(3);
1570 access_c.and_without(4);
1571
1572 access_b.append_or(&access_c);
1574 access_a.extend(&access_b);
1577
1578 let mut expected = FilteredAccess::<usize>::default();
1582 expected.add_component_write(0);
1583 expected.add_component_write(1);
1584 expected.filter_sets = vec![
1586 AccessFilters {
1587 with: FixedBitSet::with_capacity_and_blocks(3, [0b111]),
1588 without: FixedBitSet::default(),
1589 _index_type: PhantomData,
1590 },
1591 AccessFilters {
1592 with: FixedBitSet::with_capacity_and_blocks(4, [0b1011]),
1593 without: FixedBitSet::with_capacity_and_blocks(5, [0b10000]),
1594 _index_type: PhantomData,
1595 },
1596 ];
1597
1598 assert_eq!(access_a, expected);
1599 }
1600}