1use crate::component::ComponentId;
2use crate::storage::SparseSetIndex;
3use crate::world::World;
4use alloc::{format, string::String, vec, vec::Vec};
5use core::{fmt, fmt::Debug, marker::PhantomData};
6use derive_more::From;
7use disqualified::ShortName;
8use fixedbitset::FixedBitSet;
9use thiserror::Error;
10
11struct FormattedBitSet<'a, T: SparseSetIndex> {
29 bit_set: &'a FixedBitSet,
30 _marker: PhantomData<T>,
31}
32
33impl<'a, T: SparseSetIndex> FormattedBitSet<'a, T> {
34 fn new(bit_set: &'a FixedBitSet) -> Self {
35 Self {
36 bit_set,
37 _marker: PhantomData,
38 }
39 }
40}
41
42impl<'a, T: SparseSetIndex + Debug> Debug for FormattedBitSet<'a, T> {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 f.debug_list()
45 .entries(self.bit_set.ones().map(T::get_sparse_set_index))
46 .finish()
47 }
48}
49
50#[derive(Eq, PartialEq)]
55pub struct Access<T: SparseSetIndex> {
56 component_read_and_writes: FixedBitSet,
59 component_writes: FixedBitSet,
62 resource_read_and_writes: FixedBitSet,
64 resource_writes: FixedBitSet,
66 component_read_and_writes_inverted: bool,
69 component_writes_inverted: bool,
72 reads_all_resources: bool,
75 writes_all_resources: bool,
78 archetypal: FixedBitSet,
80 marker: PhantomData<T>,
81}
82
83impl<T: SparseSetIndex> Clone for Access<T> {
85 fn clone(&self) -> Self {
86 Self {
87 component_read_and_writes: self.component_read_and_writes.clone(),
88 component_writes: self.component_writes.clone(),
89 resource_read_and_writes: self.resource_read_and_writes.clone(),
90 resource_writes: self.resource_writes.clone(),
91 component_read_and_writes_inverted: self.component_read_and_writes_inverted,
92 component_writes_inverted: self.component_writes_inverted,
93 reads_all_resources: self.reads_all_resources,
94 writes_all_resources: self.writes_all_resources,
95 archetypal: self.archetypal.clone(),
96 marker: PhantomData,
97 }
98 }
99
100 fn clone_from(&mut self, source: &Self) {
101 self.component_read_and_writes
102 .clone_from(&source.component_read_and_writes);
103 self.component_writes.clone_from(&source.component_writes);
104 self.resource_read_and_writes
105 .clone_from(&source.resource_read_and_writes);
106 self.resource_writes.clone_from(&source.resource_writes);
107 self.component_read_and_writes_inverted = source.component_read_and_writes_inverted;
108 self.component_writes_inverted = source.component_writes_inverted;
109 self.reads_all_resources = source.reads_all_resources;
110 self.writes_all_resources = source.writes_all_resources;
111 self.archetypal.clone_from(&source.archetypal);
112 }
113}
114
115impl<T: SparseSetIndex + Debug> Debug for Access<T> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.debug_struct("Access")
118 .field(
119 "component_read_and_writes",
120 &FormattedBitSet::<T>::new(&self.component_read_and_writes),
121 )
122 .field(
123 "component_writes",
124 &FormattedBitSet::<T>::new(&self.component_writes),
125 )
126 .field(
127 "resource_read_and_writes",
128 &FormattedBitSet::<T>::new(&self.resource_read_and_writes),
129 )
130 .field(
131 "resource_writes",
132 &FormattedBitSet::<T>::new(&self.resource_writes),
133 )
134 .field(
135 "component_read_and_writes_inverted",
136 &self.component_read_and_writes_inverted,
137 )
138 .field("component_writes_inverted", &self.component_writes_inverted)
139 .field("reads_all_resources", &self.reads_all_resources)
140 .field("writes_all_resources", &self.writes_all_resources)
141 .field("archetypal", &FormattedBitSet::<T>::new(&self.archetypal))
142 .finish()
143 }
144}
145
146impl<T: SparseSetIndex> Default for Access<T> {
147 fn default() -> Self {
148 Self::new()
149 }
150}
151
152impl<T: SparseSetIndex> Access<T> {
153 pub const fn new() -> Self {
155 Self {
156 reads_all_resources: false,
157 writes_all_resources: false,
158 component_read_and_writes_inverted: false,
159 component_writes_inverted: false,
160 component_read_and_writes: FixedBitSet::new(),
161 component_writes: FixedBitSet::new(),
162 resource_read_and_writes: FixedBitSet::new(),
163 resource_writes: FixedBitSet::new(),
164 archetypal: FixedBitSet::new(),
165 marker: PhantomData,
166 }
167 }
168
169 fn add_component_sparse_set_index_read(&mut self, index: usize) {
170 if !self.component_read_and_writes_inverted {
171 self.component_read_and_writes.grow_and_insert(index);
172 } else if index < self.component_read_and_writes.len() {
173 self.component_read_and_writes.remove(index);
174 }
175 }
176
177 fn add_component_sparse_set_index_write(&mut self, index: usize) {
178 if !self.component_writes_inverted {
179 self.component_writes.grow_and_insert(index);
180 } else if index < self.component_writes.len() {
181 self.component_writes.remove(index);
182 }
183 }
184
185 pub fn add_component_read(&mut self, index: T) {
187 let sparse_set_index = index.sparse_set_index();
188 self.add_component_sparse_set_index_read(sparse_set_index);
189 }
190
191 pub fn add_component_write(&mut self, index: T) {
193 let sparse_set_index = index.sparse_set_index();
194 self.add_component_sparse_set_index_read(sparse_set_index);
195 self.add_component_sparse_set_index_write(sparse_set_index);
196 }
197
198 pub fn add_resource_read(&mut self, index: T) {
200 self.resource_read_and_writes
201 .grow_and_insert(index.sparse_set_index());
202 }
203
204 pub fn add_resource_write(&mut self, index: T) {
206 self.resource_read_and_writes
207 .grow_and_insert(index.sparse_set_index());
208 self.resource_writes
209 .grow_and_insert(index.sparse_set_index());
210 }
211
212 fn remove_component_sparse_set_index_read(&mut self, index: usize) {
213 if self.component_read_and_writes_inverted {
214 self.component_read_and_writes.grow_and_insert(index);
215 } else if index < self.component_read_and_writes.len() {
216 self.component_read_and_writes.remove(index);
217 }
218 }
219
220 fn remove_component_sparse_set_index_write(&mut self, index: usize) {
221 if self.component_writes_inverted {
222 self.component_writes.grow_and_insert(index);
223 } else if index < self.component_writes.len() {
224 self.component_writes.remove(index);
225 }
226 }
227
228 pub fn remove_component_read(&mut self, index: T) {
237 let sparse_set_index = index.sparse_set_index();
238 self.remove_component_sparse_set_index_write(sparse_set_index);
239 self.remove_component_sparse_set_index_read(sparse_set_index);
240 }
241
242 pub fn remove_component_write(&mut self, index: T) {
251 let sparse_set_index = index.sparse_set_index();
252 self.remove_component_sparse_set_index_write(sparse_set_index);
253 }
254
255 pub fn add_archetypal(&mut self, index: T) {
264 self.archetypal.grow_and_insert(index.sparse_set_index());
265 }
266
267 pub fn has_component_read(&self, index: T) -> bool {
269 self.component_read_and_writes_inverted
270 ^ self
271 .component_read_and_writes
272 .contains(index.sparse_set_index())
273 }
274
275 pub fn has_any_component_read(&self) -> bool {
277 self.component_read_and_writes_inverted || !self.component_read_and_writes.is_clear()
278 }
279
280 pub fn has_component_write(&self, index: T) -> bool {
282 self.component_writes_inverted ^ self.component_writes.contains(index.sparse_set_index())
283 }
284
285 pub fn has_any_component_write(&self) -> bool {
287 self.component_writes_inverted || !self.component_writes.is_clear()
288 }
289
290 pub fn has_resource_read(&self, index: T) -> bool {
292 self.reads_all_resources
293 || self
294 .resource_read_and_writes
295 .contains(index.sparse_set_index())
296 }
297
298 pub fn has_any_resource_read(&self) -> bool {
300 self.reads_all_resources || !self.resource_read_and_writes.is_clear()
301 }
302
303 pub fn has_resource_write(&self, index: T) -> bool {
305 self.writes_all_resources || self.resource_writes.contains(index.sparse_set_index())
306 }
307
308 pub fn has_any_resource_write(&self) -> bool {
310 self.writes_all_resources || !self.resource_writes.is_clear()
311 }
312
313 pub fn has_any_read(&self) -> bool {
315 self.has_any_component_read() || self.has_any_resource_read()
316 }
317
318 pub fn has_any_write(&self) -> bool {
320 self.has_any_component_write() || self.has_any_resource_write()
321 }
322
323 pub fn has_archetypal(&self, index: T) -> bool {
332 self.archetypal.contains(index.sparse_set_index())
333 }
334
335 #[inline]
337 pub fn read_all_components(&mut self) {
338 self.component_read_and_writes_inverted = true;
339 self.component_read_and_writes.clear();
340 }
341
342 #[inline]
344 pub fn write_all_components(&mut self) {
345 self.read_all_components();
346 self.component_writes_inverted = true;
347 self.component_writes.clear();
348 }
349
350 #[inline]
352 pub const fn read_all_resources(&mut self) {
353 self.reads_all_resources = true;
354 }
355
356 #[inline]
358 pub const fn write_all_resources(&mut self) {
359 self.reads_all_resources = true;
360 self.writes_all_resources = true;
361 }
362
363 #[inline]
365 pub fn read_all(&mut self) {
366 self.read_all_components();
367 self.read_all_resources();
368 }
369
370 #[inline]
372 pub fn write_all(&mut self) {
373 self.write_all_components();
374 self.write_all_resources();
375 }
376
377 #[inline]
379 pub fn has_read_all_components(&self) -> bool {
380 self.component_read_and_writes_inverted && self.component_read_and_writes.is_clear()
381 }
382
383 #[inline]
385 pub fn has_write_all_components(&self) -> bool {
386 self.component_writes_inverted && self.component_writes.is_clear()
387 }
388
389 #[inline]
391 pub fn has_read_all_resources(&self) -> bool {
392 self.reads_all_resources
393 }
394
395 #[inline]
397 pub fn has_write_all_resources(&self) -> bool {
398 self.writes_all_resources
399 }
400
401 pub fn has_read_all(&self) -> bool {
403 self.has_read_all_components() && self.has_read_all_resources()
404 }
405
406 pub fn has_write_all(&self) -> bool {
408 self.has_write_all_components() && self.has_write_all_resources()
409 }
410
411 pub fn clear_writes(&mut self) {
413 self.writes_all_resources = false;
414 self.component_writes_inverted = false;
415 self.component_writes.clear();
416 self.resource_writes.clear();
417 }
418
419 pub fn clear(&mut self) {
421 self.reads_all_resources = false;
422 self.writes_all_resources = false;
423 self.component_read_and_writes_inverted = false;
424 self.component_writes_inverted = false;
425 self.component_read_and_writes.clear();
426 self.component_writes.clear();
427 self.resource_read_and_writes.clear();
428 self.resource_writes.clear();
429 }
430
431 pub fn extend(&mut self, other: &Access<T>) {
433 let component_read_and_writes_inverted =
434 self.component_read_and_writes_inverted || other.component_read_and_writes_inverted;
435 let component_writes_inverted =
436 self.component_writes_inverted || other.component_writes_inverted;
437
438 match (
439 self.component_read_and_writes_inverted,
440 other.component_read_and_writes_inverted,
441 ) {
442 (true, true) => {
443 self.component_read_and_writes
444 .intersect_with(&other.component_read_and_writes);
445 }
446 (true, false) => {
447 self.component_read_and_writes
448 .difference_with(&other.component_read_and_writes);
449 }
450 (false, true) => {
451 self.component_read_and_writes.grow(
453 self.component_read_and_writes
454 .len()
455 .max(other.component_read_and_writes.len()),
456 );
457 self.component_read_and_writes.toggle_range(..);
458 self.component_read_and_writes
459 .intersect_with(&other.component_read_and_writes);
460 }
461 (false, false) => {
462 self.component_read_and_writes
463 .union_with(&other.component_read_and_writes);
464 }
465 }
466
467 match (
468 self.component_writes_inverted,
469 other.component_writes_inverted,
470 ) {
471 (true, true) => {
472 self.component_writes
473 .intersect_with(&other.component_writes);
474 }
475 (true, false) => {
476 self.component_writes
477 .difference_with(&other.component_writes);
478 }
479 (false, true) => {
480 self.component_writes.grow(
482 self.component_writes
483 .len()
484 .max(other.component_writes.len()),
485 );
486 self.component_writes.toggle_range(..);
487 self.component_writes
488 .intersect_with(&other.component_writes);
489 }
490 (false, false) => {
491 self.component_writes.union_with(&other.component_writes);
492 }
493 }
494
495 self.reads_all_resources = self.reads_all_resources || other.reads_all_resources;
496 self.writes_all_resources = self.writes_all_resources || other.writes_all_resources;
497 self.component_read_and_writes_inverted = component_read_and_writes_inverted;
498 self.component_writes_inverted = component_writes_inverted;
499 self.resource_read_and_writes
500 .union_with(&other.resource_read_and_writes);
501 self.resource_writes.union_with(&other.resource_writes);
502 }
503
504 pub fn is_components_compatible(&self, other: &Access<T>) -> bool {
510 for (
513 lhs_writes,
514 rhs_reads_and_writes,
515 lhs_writes_inverted,
516 rhs_reads_and_writes_inverted,
517 ) in [
518 (
519 &self.component_writes,
520 &other.component_read_and_writes,
521 self.component_writes_inverted,
522 other.component_read_and_writes_inverted,
523 ),
524 (
525 &other.component_writes,
526 &self.component_read_and_writes,
527 other.component_writes_inverted,
528 self.component_read_and_writes_inverted,
529 ),
530 ] {
531 match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
532 (true, true) => return false,
533 (false, true) => {
534 if !lhs_writes.is_subset(rhs_reads_and_writes) {
535 return false;
536 }
537 }
538 (true, false) => {
539 if !rhs_reads_and_writes.is_subset(lhs_writes) {
540 return false;
541 }
542 }
543 (false, false) => {
544 if !lhs_writes.is_disjoint(rhs_reads_and_writes) {
545 return false;
546 }
547 }
548 }
549 }
550
551 true
552 }
553
554 pub fn is_resources_compatible(&self, other: &Access<T>) -> bool {
560 if self.writes_all_resources {
561 return !other.has_any_resource_read();
562 }
563
564 if other.writes_all_resources {
565 return !self.has_any_resource_read();
566 }
567
568 if self.reads_all_resources {
569 return !other.has_any_resource_write();
570 }
571
572 if other.reads_all_resources {
573 return !self.has_any_resource_write();
574 }
575
576 self.resource_writes
577 .is_disjoint(&other.resource_read_and_writes)
578 && other
579 .resource_writes
580 .is_disjoint(&self.resource_read_and_writes)
581 }
582
583 pub fn is_compatible(&self, other: &Access<T>) -> bool {
588 self.is_components_compatible(other) && self.is_resources_compatible(other)
589 }
590
591 pub fn is_subset_components(&self, other: &Access<T>) -> bool {
594 for (
595 our_components,
596 their_components,
597 our_components_inverted,
598 their_components_inverted,
599 ) in [
600 (
601 &self.component_read_and_writes,
602 &other.component_read_and_writes,
603 self.component_read_and_writes_inverted,
604 other.component_read_and_writes_inverted,
605 ),
606 (
607 &self.component_writes,
608 &other.component_writes,
609 self.component_writes_inverted,
610 other.component_writes_inverted,
611 ),
612 ] {
613 match (our_components_inverted, their_components_inverted) {
614 (true, true) => {
615 if !their_components.is_subset(our_components) {
616 return false;
617 }
618 }
619 (true, false) => {
620 return false;
621 }
622 (false, true) => {
623 if !our_components.is_disjoint(their_components) {
624 return false;
625 }
626 }
627 (false, false) => {
628 if !our_components.is_subset(their_components) {
629 return false;
630 }
631 }
632 }
633 }
634
635 true
636 }
637
638 pub fn is_subset_resources(&self, other: &Access<T>) -> bool {
641 if self.writes_all_resources {
642 return other.writes_all_resources;
643 }
644
645 if other.writes_all_resources {
646 return true;
647 }
648
649 if self.reads_all_resources {
650 return other.reads_all_resources;
651 }
652
653 if other.reads_all_resources {
654 return self.resource_writes.is_subset(&other.resource_writes);
655 }
656
657 self.resource_read_and_writes
658 .is_subset(&other.resource_read_and_writes)
659 && self.resource_writes.is_subset(&other.resource_writes)
660 }
661
662 pub fn is_subset(&self, other: &Access<T>) -> bool {
665 self.is_subset_components(other) && self.is_subset_resources(other)
666 }
667
668 fn get_component_conflicts(&self, other: &Access<T>) -> AccessConflicts {
669 let mut conflicts = FixedBitSet::new();
670
671 for (
674 lhs_writes,
675 rhs_reads_and_writes,
676 lhs_writes_inverted,
677 rhs_reads_and_writes_inverted,
678 ) in [
679 (
680 &self.component_writes,
681 &other.component_read_and_writes,
682 self.component_writes_inverted,
683 other.component_read_and_writes_inverted,
684 ),
685 (
686 &other.component_writes,
687 &self.component_read_and_writes,
688 other.component_writes_inverted,
689 self.component_read_and_writes_inverted,
690 ),
691 ] {
692 let temp_conflicts: FixedBitSet =
695 match (lhs_writes_inverted, rhs_reads_and_writes_inverted) {
696 (true, true) => return AccessConflicts::All,
697 (false, true) => lhs_writes.difference(rhs_reads_and_writes).collect(),
698 (true, false) => rhs_reads_and_writes.difference(lhs_writes).collect(),
699 (false, false) => lhs_writes.intersection(rhs_reads_and_writes).collect(),
700 };
701 conflicts.union_with(&temp_conflicts);
702 }
703
704 AccessConflicts::Individual(conflicts)
705 }
706
707 pub fn get_conflicts(&self, other: &Access<T>) -> AccessConflicts {
709 let mut conflicts = match self.get_component_conflicts(other) {
710 AccessConflicts::All => return AccessConflicts::All,
711 AccessConflicts::Individual(conflicts) => conflicts,
712 };
713
714 if self.reads_all_resources {
715 if other.writes_all_resources {
716 return AccessConflicts::All;
717 }
718 conflicts.extend(other.resource_writes.ones());
719 }
720
721 if other.reads_all_resources {
722 if self.writes_all_resources {
723 return AccessConflicts::All;
724 }
725 conflicts.extend(self.resource_writes.ones());
726 }
727 if self.writes_all_resources {
728 conflicts.extend(other.resource_read_and_writes.ones());
729 }
730
731 if other.writes_all_resources {
732 conflicts.extend(self.resource_read_and_writes.ones());
733 }
734
735 conflicts.extend(
736 self.resource_writes
737 .intersection(&other.resource_read_and_writes),
738 );
739 conflicts.extend(
740 self.resource_read_and_writes
741 .intersection(&other.resource_writes),
742 );
743 AccessConflicts::Individual(conflicts)
744 }
745
746 pub fn resource_reads_and_writes(&self) -> impl Iterator<Item = T> + '_ {
748 self.resource_read_and_writes
749 .ones()
750 .map(T::get_sparse_set_index)
751 }
752
753 pub fn resource_reads(&self) -> impl Iterator<Item = T> + '_ {
755 self.resource_read_and_writes
756 .difference(&self.resource_writes)
757 .map(T::get_sparse_set_index)
758 }
759
760 pub fn resource_writes(&self) -> impl Iterator<Item = T> + '_ {
762 self.resource_writes.ones().map(T::get_sparse_set_index)
763 }
764
765 pub fn archetypal(&self) -> impl Iterator<Item = T> + '_ {
774 self.archetypal.ones().map(T::get_sparse_set_index)
775 }
776
777 pub fn try_iter_component_access(
807 &self,
808 ) -> Result<impl Iterator<Item = ComponentAccessKind<T>> + '_, UnboundedAccessError> {
809 if self.component_read_and_writes_inverted {
812 return Err(UnboundedAccessError {
813 writes_inverted: self.component_writes_inverted,
814 read_and_writes_inverted: self.component_read_and_writes_inverted,
815 });
816 }
817
818 let reads_and_writes = self.component_read_and_writes.ones().map(|index| {
819 let sparse_index = T::get_sparse_set_index(index);
820
821 if self.component_writes.contains(index) {
822 ComponentAccessKind::Exclusive(sparse_index)
823 } else {
824 ComponentAccessKind::Shared(sparse_index)
825 }
826 });
827
828 let archetypal = self
829 .archetypal
830 .ones()
831 .filter(|&index| {
832 !self.component_writes.contains(index)
833 && !self.component_read_and_writes.contains(index)
834 })
835 .map(|index| ComponentAccessKind::Archetypal(T::get_sparse_set_index(index)));
836
837 Ok(reads_and_writes.chain(archetypal))
838 }
839}
840
841#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
844#[error("Access is unbounded")]
845pub struct UnboundedAccessError {
846 pub writes_inverted: bool,
849 pub read_and_writes_inverted: bool,
852}
853
854#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
856pub enum ComponentAccessKind<T> {
857 Archetypal(T),
859 Shared(T),
861 Exclusive(T),
863}
864
865impl<T> ComponentAccessKind<T> {
866 pub fn index(&self) -> &T {
868 let (Self::Archetypal(value) | Self::Shared(value) | Self::Exclusive(value)) = self;
869 value
870 }
871}
872
873#[derive(Debug, Eq, PartialEq)]
894pub struct FilteredAccess<T: SparseSetIndex> {
895 pub(crate) access: Access<T>,
896 pub(crate) required: FixedBitSet,
897 pub(crate) filter_sets: Vec<AccessFilters<T>>,
900}
901
902impl<T: SparseSetIndex> Clone for FilteredAccess<T> {
904 fn clone(&self) -> Self {
905 Self {
906 access: self.access.clone(),
907 required: self.required.clone(),
908 filter_sets: self.filter_sets.clone(),
909 }
910 }
911
912 fn clone_from(&mut self, source: &Self) {
913 self.access.clone_from(&source.access);
914 self.required.clone_from(&source.required);
915 self.filter_sets.clone_from(&source.filter_sets);
916 }
917}
918
919impl<T: SparseSetIndex> Default for FilteredAccess<T> {
920 fn default() -> Self {
921 Self::matches_everything()
922 }
923}
924
925impl<T: SparseSetIndex> From<FilteredAccess<T>> for FilteredAccessSet<T> {
926 fn from(filtered_access: FilteredAccess<T>) -> Self {
927 let mut base = FilteredAccessSet::<T>::default();
928 base.add(filtered_access);
929 base
930 }
931}
932
933#[derive(Debug, PartialEq, From)]
935pub enum AccessConflicts {
936 All,
938 Individual(FixedBitSet),
940}
941
942impl AccessConflicts {
943 fn add(&mut self, other: &Self) {
944 match (self, other) {
945 (s, AccessConflicts::All) => {
946 *s = AccessConflicts::All;
947 }
948 (AccessConflicts::Individual(this), AccessConflicts::Individual(other)) => {
949 this.extend(other.ones());
950 }
951 _ => {}
952 }
953 }
954
955 pub(crate) fn is_empty(&self) -> bool {
956 match self {
957 Self::All => false,
958 Self::Individual(set) => set.is_empty(),
959 }
960 }
961
962 pub(crate) fn format_conflict_list(&self, world: &World) -> String {
963 match self {
964 AccessConflicts::All => String::new(),
965 AccessConflicts::Individual(indices) => indices
966 .ones()
967 .map(|index| {
968 format!(
969 "{}",
970 ShortName(
971 &world
972 .components
973 .get_name(ComponentId::get_sparse_set_index(index))
974 .unwrap()
975 )
976 )
977 })
978 .collect::<Vec<_>>()
979 .join(", "),
980 }
981 }
982
983 pub(crate) fn empty() -> Self {
985 Self::Individual(FixedBitSet::new())
986 }
987}
988
989impl<T: SparseSetIndex> From<Vec<T>> for AccessConflicts {
990 fn from(value: Vec<T>) -> Self {
991 Self::Individual(value.iter().map(T::sparse_set_index).collect())
992 }
993}
994
995impl<T: SparseSetIndex> FilteredAccess<T> {
996 pub fn matches_everything() -> Self {
999 Self {
1000 access: Access::default(),
1001 required: FixedBitSet::default(),
1002 filter_sets: vec![AccessFilters::default()],
1003 }
1004 }
1005
1006 pub fn matches_nothing() -> Self {
1009 Self {
1010 access: Access::default(),
1011 required: FixedBitSet::default(),
1012 filter_sets: Vec::new(),
1013 }
1014 }
1015
1016 #[inline]
1018 pub fn access(&self) -> &Access<T> {
1019 &self.access
1020 }
1021
1022 #[inline]
1024 pub fn access_mut(&mut self) -> &mut Access<T> {
1025 &mut self.access
1026 }
1027
1028 pub fn add_component_read(&mut self, index: T) {
1030 self.access.add_component_read(index.clone());
1031 self.add_required(index.clone());
1032 self.and_with(index);
1033 }
1034
1035 pub fn add_component_write(&mut self, index: T) {
1037 self.access.add_component_write(index.clone());
1038 self.add_required(index.clone());
1039 self.and_with(index);
1040 }
1041
1042 pub fn add_resource_read(&mut self, index: T) {
1044 self.access.add_resource_read(index.clone());
1045 }
1046
1047 pub fn add_resource_write(&mut self, index: T) {
1049 self.access.add_resource_write(index.clone());
1050 }
1051
1052 fn add_required(&mut self, index: T) {
1053 self.required.grow_and_insert(index.sparse_set_index());
1054 }
1055
1056 pub fn and_with(&mut self, index: T) {
1061 for filter in &mut self.filter_sets {
1062 filter.with.grow_and_insert(index.sparse_set_index());
1063 }
1064 }
1065
1066 pub fn and_without(&mut self, index: T) {
1071 for filter in &mut self.filter_sets {
1072 filter.without.grow_and_insert(index.sparse_set_index());
1073 }
1074 }
1075
1076 pub fn append_or(&mut self, other: &FilteredAccess<T>) {
1082 self.filter_sets.append(&mut other.filter_sets.clone());
1083 }
1084
1085 pub fn extend_access(&mut self, other: &FilteredAccess<T>) {
1087 self.access.extend(&other.access);
1088 }
1089
1090 pub fn is_compatible(&self, other: &FilteredAccess<T>) -> bool {
1092 if !self.access.is_resources_compatible(&other.access) {
1095 return false;
1096 }
1097
1098 if self.access.is_components_compatible(&other.access) {
1099 return true;
1100 }
1101
1102 self.filter_sets.iter().all(|filter| {
1110 other
1111 .filter_sets
1112 .iter()
1113 .all(|other_filter| filter.is_ruled_out_by(other_filter))
1114 })
1115 }
1116
1117 pub fn get_conflicts(&self, other: &FilteredAccess<T>) -> AccessConflicts {
1119 if !self.is_compatible(other) {
1120 return self.access.get_conflicts(&other.access);
1122 }
1123 AccessConflicts::empty()
1124 }
1125
1126 pub fn extend(&mut self, other: &FilteredAccess<T>) {
1133 self.access.extend(&other.access);
1134 self.required.union_with(&other.required);
1135
1136 if other.filter_sets.len() == 1 {
1139 for filter in &mut self.filter_sets {
1140 filter.with.union_with(&other.filter_sets[0].with);
1141 filter.without.union_with(&other.filter_sets[0].without);
1142 }
1143 return;
1144 }
1145
1146 let mut new_filters = Vec::with_capacity(self.filter_sets.len() * other.filter_sets.len());
1147 for filter in &self.filter_sets {
1148 for other_filter in &other.filter_sets {
1149 let mut new_filter = filter.clone();
1150 new_filter.with.union_with(&other_filter.with);
1151 new_filter.without.union_with(&other_filter.without);
1152 new_filters.push(new_filter);
1153 }
1154 }
1155 self.filter_sets = new_filters;
1156 }
1157
1158 pub fn read_all(&mut self) {
1160 self.access.read_all();
1161 }
1162
1163 pub fn write_all(&mut self) {
1165 self.access.write_all();
1166 }
1167
1168 pub fn read_all_components(&mut self) {
1170 self.access.read_all_components();
1171 }
1172
1173 pub fn write_all_components(&mut self) {
1175 self.access.write_all_components();
1176 }
1177
1178 pub fn is_subset(&self, other: &FilteredAccess<T>) -> bool {
1181 self.required.is_subset(&other.required) && self.access().is_subset(other.access())
1182 }
1183
1184 pub fn with_filters(&self) -> impl Iterator<Item = T> + '_ {
1186 self.filter_sets
1187 .iter()
1188 .flat_map(|f| f.with.ones().map(T::get_sparse_set_index))
1189 }
1190
1191 pub fn without_filters(&self) -> impl Iterator<Item = T> + '_ {
1193 self.filter_sets
1194 .iter()
1195 .flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
1196 }
1197
1198 pub fn contains(&self, index: T) -> bool {
1200 self.access().has_component_read(index.clone())
1201 || self.access().has_archetypal(index.clone())
1202 || self.filter_sets.iter().any(|f| {
1203 f.with.contains(index.sparse_set_index())
1204 || f.without.contains(index.sparse_set_index())
1205 })
1206 }
1207}
1208
1209#[derive(Eq, PartialEq)]
1210pub(crate) struct AccessFilters<T> {
1211 pub(crate) with: FixedBitSet,
1212 pub(crate) without: FixedBitSet,
1213 _index_type: PhantomData<T>,
1214}
1215
1216impl<T: SparseSetIndex> Clone for AccessFilters<T> {
1218 fn clone(&self) -> Self {
1219 Self {
1220 with: self.with.clone(),
1221 without: self.without.clone(),
1222 _index_type: PhantomData,
1223 }
1224 }
1225
1226 fn clone_from(&mut self, source: &Self) {
1227 self.with.clone_from(&source.with);
1228 self.without.clone_from(&source.without);
1229 }
1230}
1231
1232impl<T: SparseSetIndex + Debug> Debug for AccessFilters<T> {
1233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1234 f.debug_struct("AccessFilters")
1235 .field("with", &FormattedBitSet::<T>::new(&self.with))
1236 .field("without", &FormattedBitSet::<T>::new(&self.without))
1237 .finish()
1238 }
1239}
1240
1241impl<T: SparseSetIndex> Default for AccessFilters<T> {
1242 fn default() -> Self {
1243 Self {
1244 with: FixedBitSet::default(),
1245 without: FixedBitSet::default(),
1246 _index_type: PhantomData,
1247 }
1248 }
1249}
1250
1251impl<T: SparseSetIndex> AccessFilters<T> {
1252 fn is_ruled_out_by(&self, other: &Self) -> bool {
1253 !self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
1259 }
1260}
1261
1262#[derive(Debug, PartialEq, Eq)]
1270pub struct FilteredAccessSet<T: SparseSetIndex> {
1271 combined_access: Access<T>,
1272 filtered_accesses: Vec<FilteredAccess<T>>,
1273}
1274
1275impl<T: SparseSetIndex> Clone for FilteredAccessSet<T> {
1277 fn clone(&self) -> Self {
1278 Self {
1279 combined_access: self.combined_access.clone(),
1280 filtered_accesses: self.filtered_accesses.clone(),
1281 }
1282 }
1283
1284 fn clone_from(&mut self, source: &Self) {
1285 self.combined_access.clone_from(&source.combined_access);
1286 self.filtered_accesses.clone_from(&source.filtered_accesses);
1287 }
1288}
1289
1290impl<T: SparseSetIndex> FilteredAccessSet<T> {
1291 #[inline]
1293 pub fn combined_access(&self) -> &Access<T> {
1294 &self.combined_access
1295 }
1296
1297 pub fn is_compatible(&self, other: &FilteredAccessSet<T>) -> bool {
1310 if self.combined_access.is_compatible(other.combined_access()) {
1311 return true;
1312 }
1313 for filtered in &self.filtered_accesses {
1314 for other_filtered in &other.filtered_accesses {
1315 if !filtered.is_compatible(other_filtered) {
1316 return false;
1317 }
1318 }
1319 }
1320 true
1321 }
1322
1323 pub fn get_conflicts(&self, other: &FilteredAccessSet<T>) -> AccessConflicts {
1325 let mut conflicts = AccessConflicts::empty();
1327 if !self.combined_access.is_compatible(other.combined_access()) {
1328 for filtered in &self.filtered_accesses {
1329 for other_filtered in &other.filtered_accesses {
1330 conflicts.add(&filtered.get_conflicts(other_filtered));
1331 }
1332 }
1333 }
1334 conflicts
1335 }
1336
1337 pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess<T>) -> AccessConflicts {
1339 let mut conflicts = AccessConflicts::empty();
1341 if !self.combined_access.is_compatible(filtered_access.access()) {
1342 for filtered in &self.filtered_accesses {
1343 conflicts.add(&filtered.get_conflicts(filtered_access));
1344 }
1345 }
1346 conflicts
1347 }
1348
1349 pub fn add(&mut self, filtered_access: FilteredAccess<T>) {
1351 self.combined_access.extend(&filtered_access.access);
1352 self.filtered_accesses.push(filtered_access);
1353 }
1354
1355 pub fn add_unfiltered_resource_read(&mut self, index: T) {
1357 let mut filter = FilteredAccess::default();
1358 filter.add_resource_read(index);
1359 self.add(filter);
1360 }
1361
1362 pub fn add_unfiltered_resource_write(&mut self, index: T) {
1364 let mut filter = FilteredAccess::default();
1365 filter.add_resource_write(index);
1366 self.add(filter);
1367 }
1368
1369 pub fn add_unfiltered_read_all_resources(&mut self) {
1371 let mut filter = FilteredAccess::default();
1372 filter.access.read_all_resources();
1373 self.add(filter);
1374 }
1375
1376 pub fn add_unfiltered_write_all_resources(&mut self) {
1378 let mut filter = FilteredAccess::default();
1379 filter.access.write_all_resources();
1380 self.add(filter);
1381 }
1382
1383 pub fn extend(&mut self, filtered_access_set: FilteredAccessSet<T>) {
1385 self.combined_access
1386 .extend(&filtered_access_set.combined_access);
1387 self.filtered_accesses
1388 .extend(filtered_access_set.filtered_accesses);
1389 }
1390
1391 pub fn read_all(&mut self) {
1393 let mut filter = FilteredAccess::matches_everything();
1394 filter.read_all();
1395 self.add(filter);
1396 }
1397
1398 pub fn write_all(&mut self) {
1400 let mut filter = FilteredAccess::matches_everything();
1401 filter.write_all();
1402 self.add(filter);
1403 }
1404
1405 pub fn clear(&mut self) {
1407 self.combined_access.clear();
1408 self.filtered_accesses.clear();
1409 }
1410}
1411
1412impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
1413 fn default() -> Self {
1414 Self {
1415 combined_access: Default::default(),
1416 filtered_accesses: Vec::new(),
1417 }
1418 }
1419}
1420
1421#[cfg(test)]
1422mod tests {
1423 use crate::query::{
1424 access::AccessFilters, Access, AccessConflicts, ComponentAccessKind, FilteredAccess,
1425 FilteredAccessSet, UnboundedAccessError,
1426 };
1427 use alloc::{vec, vec::Vec};
1428 use core::marker::PhantomData;
1429 use fixedbitset::FixedBitSet;
1430
1431 fn create_sample_access() -> Access<usize> {
1432 let mut access = Access::<usize>::default();
1433
1434 access.add_component_read(1);
1435 access.add_component_read(2);
1436 access.add_component_write(3);
1437 access.add_archetypal(5);
1438 access.read_all();
1439
1440 access
1441 }
1442
1443 fn create_sample_filtered_access() -> FilteredAccess<usize> {
1444 let mut filtered_access = FilteredAccess::<usize>::default();
1445
1446 filtered_access.add_component_write(1);
1447 filtered_access.add_component_read(2);
1448 filtered_access.add_required(3);
1449 filtered_access.and_with(4);
1450
1451 filtered_access
1452 }
1453
1454 fn create_sample_access_filters() -> AccessFilters<usize> {
1455 let mut access_filters = AccessFilters::<usize>::default();
1456
1457 access_filters.with.grow_and_insert(3);
1458 access_filters.without.grow_and_insert(5);
1459
1460 access_filters
1461 }
1462
1463 fn create_sample_filtered_access_set() -> FilteredAccessSet<usize> {
1464 let mut filtered_access_set = FilteredAccessSet::<usize>::default();
1465
1466 filtered_access_set.add_unfiltered_resource_read(2);
1467 filtered_access_set.add_unfiltered_resource_write(4);
1468 filtered_access_set.read_all();
1469
1470 filtered_access_set
1471 }
1472
1473 #[test]
1474 fn test_access_clone() {
1475 let original: Access<usize> = create_sample_access();
1476 let cloned = original.clone();
1477
1478 assert_eq!(original, cloned);
1479 }
1480
1481 #[test]
1482 fn test_access_clone_from() {
1483 let original: Access<usize> = create_sample_access();
1484 let mut cloned = Access::<usize>::default();
1485
1486 cloned.add_component_write(7);
1487 cloned.add_component_read(4);
1488 cloned.add_archetypal(8);
1489 cloned.write_all();
1490
1491 cloned.clone_from(&original);
1492
1493 assert_eq!(original, cloned);
1494 }
1495
1496 #[test]
1497 fn test_filtered_access_clone() {
1498 let original: FilteredAccess<usize> = create_sample_filtered_access();
1499 let cloned = original.clone();
1500
1501 assert_eq!(original, cloned);
1502 }
1503
1504 #[test]
1505 fn test_filtered_access_clone_from() {
1506 let original: FilteredAccess<usize> = create_sample_filtered_access();
1507 let mut cloned = FilteredAccess::<usize>::default();
1508
1509 cloned.add_component_write(7);
1510 cloned.add_component_read(4);
1511 cloned.append_or(&FilteredAccess::default());
1512
1513 cloned.clone_from(&original);
1514
1515 assert_eq!(original, cloned);
1516 }
1517
1518 #[test]
1519 fn test_access_filters_clone() {
1520 let original: AccessFilters<usize> = create_sample_access_filters();
1521 let cloned = original.clone();
1522
1523 assert_eq!(original, cloned);
1524 }
1525
1526 #[test]
1527 fn test_access_filters_clone_from() {
1528 let original: AccessFilters<usize> = create_sample_access_filters();
1529 let mut cloned = AccessFilters::<usize>::default();
1530
1531 cloned.with.grow_and_insert(1);
1532 cloned.without.grow_and_insert(2);
1533
1534 cloned.clone_from(&original);
1535
1536 assert_eq!(original, cloned);
1537 }
1538
1539 #[test]
1540 fn test_filtered_access_set_clone() {
1541 let original: FilteredAccessSet<usize> = create_sample_filtered_access_set();
1542 let cloned = original.clone();
1543
1544 assert_eq!(original, cloned);
1545 }
1546
1547 #[test]
1548 fn test_filtered_access_set_from() {
1549 let original: FilteredAccessSet<usize> = create_sample_filtered_access_set();
1550 let mut cloned = FilteredAccessSet::<usize>::default();
1551
1552 cloned.add_unfiltered_resource_read(7);
1553 cloned.add_unfiltered_resource_write(9);
1554 cloned.write_all();
1555
1556 cloned.clone_from(&original);
1557
1558 assert_eq!(original, cloned);
1559 }
1560
1561 #[test]
1562 fn read_all_access_conflicts() {
1563 let mut access_a = Access::<usize>::default();
1565 access_a.add_component_write(0);
1566
1567 let mut access_b = Access::<usize>::default();
1568 access_b.read_all();
1569
1570 assert!(!access_b.is_compatible(&access_a));
1571
1572 let mut access_a = Access::<usize>::default();
1574 access_a.read_all();
1575
1576 let mut access_b = Access::<usize>::default();
1577 access_b.read_all();
1578
1579 assert!(access_b.is_compatible(&access_a));
1580 }
1581
1582 #[test]
1583 fn access_get_conflicts() {
1584 let mut access_a = Access::<usize>::default();
1585 access_a.add_component_read(0);
1586 access_a.add_component_read(1);
1587
1588 let mut access_b = Access::<usize>::default();
1589 access_b.add_component_read(0);
1590 access_b.add_component_write(1);
1591
1592 assert_eq!(access_a.get_conflicts(&access_b), vec![1_usize].into());
1593
1594 let mut access_c = Access::<usize>::default();
1595 access_c.add_component_write(0);
1596 access_c.add_component_write(1);
1597
1598 assert_eq!(
1599 access_a.get_conflicts(&access_c),
1600 vec![0_usize, 1_usize].into()
1601 );
1602 assert_eq!(
1603 access_b.get_conflicts(&access_c),
1604 vec![0_usize, 1_usize].into()
1605 );
1606
1607 let mut access_d = Access::<usize>::default();
1608 access_d.add_component_read(0);
1609
1610 assert_eq!(access_d.get_conflicts(&access_a), AccessConflicts::empty());
1611 assert_eq!(access_d.get_conflicts(&access_b), AccessConflicts::empty());
1612 assert_eq!(access_d.get_conflicts(&access_c), vec![0_usize].into());
1613 }
1614
1615 #[test]
1616 fn filtered_combined_access() {
1617 let mut access_a = FilteredAccessSet::<usize>::default();
1618 access_a.add_unfiltered_resource_read(1);
1619
1620 let mut filter_b = FilteredAccess::<usize>::default();
1621 filter_b.add_resource_write(1);
1622
1623 let conflicts = access_a.get_conflicts_single(&filter_b);
1624 assert_eq!(
1625 &conflicts,
1626 &AccessConflicts::from(vec![1_usize]),
1627 "access_a: {access_a:?}, filter_b: {filter_b:?}"
1628 );
1629 }
1630
1631 #[test]
1632 fn filtered_access_extend() {
1633 let mut access_a = FilteredAccess::<usize>::default();
1634 access_a.add_component_read(0);
1635 access_a.add_component_read(1);
1636 access_a.and_with(2);
1637
1638 let mut access_b = FilteredAccess::<usize>::default();
1639 access_b.add_component_read(0);
1640 access_b.add_component_write(3);
1641 access_b.and_without(4);
1642
1643 access_a.extend(&access_b);
1644
1645 let mut expected = FilteredAccess::<usize>::default();
1646 expected.add_component_read(0);
1647 expected.add_component_read(1);
1648 expected.and_with(2);
1649 expected.add_component_write(3);
1650 expected.and_without(4);
1651
1652 assert!(access_a.eq(&expected));
1653 }
1654
1655 #[test]
1656 fn filtered_access_extend_or() {
1657 let mut access_a = FilteredAccess::<usize>::default();
1658 access_a.add_component_write(0);
1660 access_a.add_component_write(1);
1661
1662 let mut access_b = FilteredAccess::<usize>::default();
1664 access_b.and_with(2);
1665
1666 let mut access_c = FilteredAccess::<usize>::default();
1668 access_c.and_with(3);
1669 access_c.and_without(4);
1670
1671 access_b.append_or(&access_c);
1673 access_a.extend(&access_b);
1676
1677 let mut expected = FilteredAccess::<usize>::default();
1681 expected.add_component_write(0);
1682 expected.add_component_write(1);
1683 expected.filter_sets = vec![
1685 AccessFilters {
1686 with: FixedBitSet::with_capacity_and_blocks(3, [0b111]),
1687 without: FixedBitSet::default(),
1688 _index_type: PhantomData,
1689 },
1690 AccessFilters {
1691 with: FixedBitSet::with_capacity_and_blocks(4, [0b1011]),
1692 without: FixedBitSet::with_capacity_and_blocks(5, [0b10000]),
1693 _index_type: PhantomData,
1694 },
1695 ];
1696
1697 assert_eq!(access_a, expected);
1698 }
1699
1700 #[test]
1701 fn try_iter_component_access_simple() {
1702 let mut access = Access::<usize>::default();
1703
1704 access.add_component_read(1);
1705 access.add_component_read(2);
1706 access.add_component_write(3);
1707 access.add_archetypal(5);
1708
1709 let result = access
1710 .try_iter_component_access()
1711 .map(Iterator::collect::<Vec<_>>);
1712
1713 assert_eq!(
1714 result,
1715 Ok(vec![
1716 ComponentAccessKind::Shared(1),
1717 ComponentAccessKind::Shared(2),
1718 ComponentAccessKind::Exclusive(3),
1719 ComponentAccessKind::Archetypal(5),
1720 ]),
1721 );
1722 }
1723
1724 #[test]
1725 fn try_iter_component_access_unbounded_write_all() {
1726 let mut access = Access::<usize>::default();
1727
1728 access.add_component_read(1);
1729 access.add_component_read(2);
1730 access.write_all();
1731
1732 let result = access
1733 .try_iter_component_access()
1734 .map(Iterator::collect::<Vec<_>>);
1735
1736 assert_eq!(
1737 result,
1738 Err(UnboundedAccessError {
1739 writes_inverted: true,
1740 read_and_writes_inverted: true
1741 }),
1742 );
1743 }
1744
1745 #[test]
1746 fn try_iter_component_access_unbounded_read_all() {
1747 let mut access = Access::<usize>::default();
1748
1749 access.add_component_read(1);
1750 access.add_component_read(2);
1751 access.read_all();
1752
1753 let result = access
1754 .try_iter_component_access()
1755 .map(Iterator::collect::<Vec<_>>);
1756
1757 assert_eq!(
1758 result,
1759 Err(UnboundedAccessError {
1760 writes_inverted: false,
1761 read_and_writes_inverted: true
1762 }),
1763 );
1764 }
1765}