1use crate::storage::SparseSetIndex;
2use bevy_utils::HashSet;
3use core::fmt;
4use fixedbitset::FixedBitSet;
5use std::marker::PhantomData;
6
7struct FormattedBitSet<'a, T: SparseSetIndex> {
25 bit_set: &'a FixedBitSet,
26 _marker: PhantomData<T>,
27}
28
29impl<'a, T: SparseSetIndex> FormattedBitSet<'a, T> {
30 fn new(bit_set: &'a FixedBitSet) -> Self {
31 Self {
32 bit_set,
33 _marker: PhantomData,
34 }
35 }
36}
37
38impl<'a, T: SparseSetIndex + fmt::Debug> fmt::Debug for FormattedBitSet<'a, T> {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_list()
41 .entries(self.bit_set.ones().map(T::get_sparse_set_index))
42 .finish()
43 }
44}
45
46#[derive(Clone, Eq, PartialEq)]
51pub struct Access<T: SparseSetIndex> {
52 reads_and_writes: FixedBitSet,
54 writes: FixedBitSet,
56 reads_all: bool,
59 writes_all: bool,
62 archetypal: FixedBitSet,
64 marker: PhantomData<T>,
65}
66
67impl<T: SparseSetIndex + fmt::Debug> fmt::Debug for Access<T> {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69 f.debug_struct("Access")
70 .field(
71 "read_and_writes",
72 &FormattedBitSet::<T>::new(&self.reads_and_writes),
73 )
74 .field("writes", &FormattedBitSet::<T>::new(&self.writes))
75 .field("reads_all", &self.reads_all)
76 .field("writes_all", &self.writes_all)
77 .field("archetypal", &FormattedBitSet::<T>::new(&self.archetypal))
78 .finish()
79 }
80}
81
82impl<T: SparseSetIndex> Default for Access<T> {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88impl<T: SparseSetIndex> Access<T> {
89 pub const fn new() -> Self {
91 Self {
92 reads_all: false,
93 writes_all: false,
94 reads_and_writes: FixedBitSet::new(),
95 writes: FixedBitSet::new(),
96 archetypal: FixedBitSet::new(),
97 marker: PhantomData,
98 }
99 }
100
101 pub fn add_read(&mut self, index: T) {
103 self.reads_and_writes
104 .grow_and_insert(index.sparse_set_index());
105 }
106
107 pub fn add_write(&mut self, index: T) {
109 self.reads_and_writes
110 .grow_and_insert(index.sparse_set_index());
111 self.writes.grow_and_insert(index.sparse_set_index());
112 }
113
114 pub fn add_archetypal(&mut self, index: T) {
123 self.archetypal.grow_and_insert(index.sparse_set_index());
124 }
125
126 pub fn has_read(&self, index: T) -> bool {
128 self.reads_all || self.reads_and_writes.contains(index.sparse_set_index())
129 }
130
131 pub fn has_any_read(&self) -> bool {
133 self.reads_all || !self.reads_and_writes.is_clear()
134 }
135
136 pub fn has_write(&self, index: T) -> bool {
138 self.writes_all || self.writes.contains(index.sparse_set_index())
139 }
140
141 pub fn has_any_write(&self) -> bool {
143 self.writes_all || !self.writes.is_clear()
144 }
145
146 pub fn has_archetypal(&self, index: T) -> bool {
155 self.archetypal.contains(index.sparse_set_index())
156 }
157
158 pub fn read_all(&mut self) {
160 self.reads_all = true;
161 }
162
163 pub fn write_all(&mut self) {
165 self.reads_all = true;
166 self.writes_all = true;
167 }
168
169 pub fn has_read_all(&self) -> bool {
171 self.reads_all
172 }
173
174 pub fn has_write_all(&self) -> bool {
176 self.writes_all
177 }
178
179 pub fn clear_writes(&mut self) {
181 self.writes_all = false;
182 self.writes.clear();
183 }
184
185 pub fn clear(&mut self) {
187 self.reads_all = false;
188 self.writes_all = false;
189 self.reads_and_writes.clear();
190 self.writes.clear();
191 }
192
193 pub fn extend(&mut self, other: &Access<T>) {
195 self.reads_all = self.reads_all || other.reads_all;
196 self.writes_all = self.writes_all || other.writes_all;
197 self.reads_and_writes.union_with(&other.reads_and_writes);
198 self.writes.union_with(&other.writes);
199 }
200
201 pub fn is_compatible(&self, other: &Access<T>) -> bool {
206 if self.writes_all {
207 return !other.has_any_read();
208 }
209
210 if other.writes_all {
211 return !self.has_any_read();
212 }
213
214 if self.reads_all {
215 return !other.has_any_write();
216 }
217
218 if other.reads_all {
219 return !self.has_any_write();
220 }
221
222 self.writes.is_disjoint(&other.reads_and_writes)
223 && other.writes.is_disjoint(&self.reads_and_writes)
224 }
225
226 pub fn is_subset(&self, other: &Access<T>) -> bool {
229 if self.writes_all {
230 return other.writes_all;
231 }
232
233 if other.writes_all {
234 return true;
235 }
236
237 if self.reads_all {
238 return other.reads_all;
239 }
240
241 if other.reads_all {
242 return self.writes.is_subset(&other.writes);
243 }
244
245 self.reads_and_writes.is_subset(&other.reads_and_writes)
246 && self.writes.is_subset(&other.writes)
247 }
248
249 pub fn get_conflicts(&self, other: &Access<T>) -> Vec<T> {
251 let mut conflicts = FixedBitSet::default();
252 if self.reads_all {
253 conflicts.extend(other.writes.ones());
255 }
256
257 if other.reads_all {
258 conflicts.extend(self.writes.ones());
260 }
261
262 if self.writes_all {
263 conflicts.extend(other.reads_and_writes.ones());
264 }
265
266 if other.writes_all {
267 conflicts.extend(self.reads_and_writes.ones());
268 }
269
270 conflicts.extend(self.writes.intersection(&other.reads_and_writes));
271 conflicts.extend(self.reads_and_writes.intersection(&other.writes));
272 conflicts
273 .ones()
274 .map(SparseSetIndex::get_sparse_set_index)
275 .collect()
276 }
277
278 pub fn reads_and_writes(&self) -> impl Iterator<Item = T> + '_ {
280 self.reads_and_writes.ones().map(T::get_sparse_set_index)
281 }
282
283 pub fn reads(&self) -> impl Iterator<Item = T> + '_ {
285 self.reads_and_writes
286 .difference(&self.writes)
287 .map(T::get_sparse_set_index)
288 }
289
290 pub fn writes(&self) -> impl Iterator<Item = T> + '_ {
292 self.writes.ones().map(T::get_sparse_set_index)
293 }
294
295 pub fn archetypal(&self) -> impl Iterator<Item = T> + '_ {
304 self.archetypal.ones().map(T::get_sparse_set_index)
305 }
306}
307
308#[derive(Debug, Clone, Eq, PartialEq)]
329pub struct FilteredAccess<T: SparseSetIndex> {
330 pub(crate) access: Access<T>,
331 pub(crate) required: FixedBitSet,
332 pub(crate) filter_sets: Vec<AccessFilters<T>>,
335}
336
337impl<T: SparseSetIndex> Default for FilteredAccess<T> {
338 fn default() -> Self {
339 Self {
340 access: Access::default(),
341 required: FixedBitSet::default(),
342 filter_sets: vec![AccessFilters::default()],
343 }
344 }
345}
346
347impl<T: SparseSetIndex> From<FilteredAccess<T>> for FilteredAccessSet<T> {
348 fn from(filtered_access: FilteredAccess<T>) -> Self {
349 let mut base = FilteredAccessSet::<T>::default();
350 base.add(filtered_access);
351 base
352 }
353}
354
355impl<T: SparseSetIndex> FilteredAccess<T> {
356 #[inline]
358 pub fn access(&self) -> &Access<T> {
359 &self.access
360 }
361
362 #[inline]
364 pub fn access_mut(&mut self) -> &mut Access<T> {
365 &mut self.access
366 }
367
368 pub fn add_read(&mut self, index: T) {
370 self.access.add_read(index.clone());
371 self.add_required(index.clone());
372 self.and_with(index);
373 }
374
375 pub fn add_write(&mut self, index: T) {
377 self.access.add_write(index.clone());
378 self.add_required(index.clone());
379 self.and_with(index);
380 }
381
382 fn add_required(&mut self, index: T) {
383 self.required.grow_and_insert(index.sparse_set_index());
384 }
385
386 pub fn and_with(&mut self, index: T) {
391 for filter in &mut self.filter_sets {
392 filter.with.grow_and_insert(index.sparse_set_index());
393 }
394 }
395
396 pub fn and_without(&mut self, index: T) {
401 for filter in &mut self.filter_sets {
402 filter.without.grow_and_insert(index.sparse_set_index());
403 }
404 }
405
406 pub fn append_or(&mut self, other: &FilteredAccess<T>) {
412 self.filter_sets.append(&mut other.filter_sets.clone());
413 }
414
415 pub fn extend_access(&mut self, other: &FilteredAccess<T>) {
417 self.access.extend(&other.access);
418 }
419
420 pub fn is_compatible(&self, other: &FilteredAccess<T>) -> bool {
422 if self.access.is_compatible(&other.access) {
423 return true;
424 }
425
426 self.filter_sets.iter().all(|filter| {
434 other
435 .filter_sets
436 .iter()
437 .all(|other_filter| filter.is_ruled_out_by(other_filter))
438 })
439 }
440
441 pub fn get_conflicts(&self, other: &FilteredAccess<T>) -> Vec<T> {
443 if !self.is_compatible(other) {
444 return self.access.get_conflicts(&other.access);
446 }
447 Vec::new()
448 }
449
450 pub fn extend(&mut self, other: &FilteredAccess<T>) {
457 self.access.extend(&other.access);
458 self.required.union_with(&other.required);
459
460 if other.filter_sets.len() == 1 {
463 for filter in &mut self.filter_sets {
464 filter.with.union_with(&other.filter_sets[0].with);
465 filter.without.union_with(&other.filter_sets[0].without);
466 }
467 return;
468 }
469
470 let mut new_filters = Vec::with_capacity(self.filter_sets.len() * other.filter_sets.len());
471 for filter in &self.filter_sets {
472 for other_filter in &other.filter_sets {
473 let mut new_filter = filter.clone();
474 new_filter.with.union_with(&other_filter.with);
475 new_filter.without.union_with(&other_filter.without);
476 new_filters.push(new_filter);
477 }
478 }
479 self.filter_sets = new_filters;
480 }
481
482 pub fn read_all(&mut self) {
484 self.access.read_all();
485 }
486
487 pub fn write_all(&mut self) {
489 self.access.write_all();
490 }
491
492 pub fn is_subset(&self, other: &FilteredAccess<T>) -> bool {
495 self.required.is_subset(&other.required) && self.access().is_subset(other.access())
496 }
497
498 pub fn with_filters(&self) -> impl Iterator<Item = T> + '_ {
500 self.filter_sets
501 .iter()
502 .flat_map(|f| f.with.ones().map(T::get_sparse_set_index))
503 }
504
505 pub fn without_filters(&self) -> impl Iterator<Item = T> + '_ {
507 self.filter_sets
508 .iter()
509 .flat_map(|f| f.without.ones().map(T::get_sparse_set_index))
510 }
511}
512
513#[derive(Clone, Eq, PartialEq)]
514pub(crate) struct AccessFilters<T> {
515 pub(crate) with: FixedBitSet,
516 pub(crate) without: FixedBitSet,
517 _index_type: PhantomData<T>,
518}
519
520impl<T: SparseSetIndex + fmt::Debug> fmt::Debug for AccessFilters<T> {
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 f.debug_struct("AccessFilters")
523 .field("with", &FormattedBitSet::<T>::new(&self.with))
524 .field("without", &FormattedBitSet::<T>::new(&self.without))
525 .finish()
526 }
527}
528
529impl<T: SparseSetIndex> Default for AccessFilters<T> {
530 fn default() -> Self {
531 Self {
532 with: FixedBitSet::default(),
533 without: FixedBitSet::default(),
534 _index_type: PhantomData,
535 }
536 }
537}
538
539impl<T: SparseSetIndex> AccessFilters<T> {
540 fn is_ruled_out_by(&self, other: &Self) -> bool {
541 !self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
547 }
548}
549
550#[derive(Debug, Clone)]
558pub struct FilteredAccessSet<T: SparseSetIndex> {
559 combined_access: Access<T>,
560 filtered_accesses: Vec<FilteredAccess<T>>,
561}
562
563impl<T: SparseSetIndex> FilteredAccessSet<T> {
564 #[inline]
566 pub fn combined_access(&self) -> &Access<T> {
567 &self.combined_access
568 }
569
570 pub fn is_compatible(&self, other: &FilteredAccessSet<T>) -> bool {
583 if self.combined_access.is_compatible(other.combined_access()) {
584 return true;
585 }
586 for filtered in &self.filtered_accesses {
587 for other_filtered in &other.filtered_accesses {
588 if !filtered.is_compatible(other_filtered) {
589 return false;
590 }
591 }
592 }
593 true
594 }
595
596 pub fn get_conflicts(&self, other: &FilteredAccessSet<T>) -> Vec<T> {
598 let mut conflicts = HashSet::new();
600 if !self.combined_access.is_compatible(other.combined_access()) {
601 for filtered in &self.filtered_accesses {
602 for other_filtered in &other.filtered_accesses {
603 conflicts.extend(filtered.get_conflicts(other_filtered).into_iter());
604 }
605 }
606 }
607 conflicts.into_iter().collect()
608 }
609
610 pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess<T>) -> Vec<T> {
612 let mut conflicts = HashSet::new();
614 if !self.combined_access.is_compatible(filtered_access.access()) {
615 for filtered in &self.filtered_accesses {
616 conflicts.extend(filtered.get_conflicts(filtered_access).into_iter());
617 }
618 }
619 conflicts.into_iter().collect()
620 }
621
622 pub fn add(&mut self, filtered_access: FilteredAccess<T>) {
624 self.combined_access.extend(&filtered_access.access);
625 self.filtered_accesses.push(filtered_access);
626 }
627
628 pub(crate) fn add_unfiltered_read(&mut self, index: T) {
630 let mut filter = FilteredAccess::default();
631 filter.add_read(index);
632 self.add(filter);
633 }
634
635 pub(crate) fn add_unfiltered_write(&mut self, index: T) {
637 let mut filter = FilteredAccess::default();
638 filter.add_write(index);
639 self.add(filter);
640 }
641
642 pub fn extend(&mut self, filtered_access_set: FilteredAccessSet<T>) {
644 self.combined_access
645 .extend(&filtered_access_set.combined_access);
646 self.filtered_accesses
647 .extend(filtered_access_set.filtered_accesses);
648 }
649
650 pub fn read_all(&mut self) {
652 self.combined_access.read_all();
653 }
654
655 pub fn write_all(&mut self) {
657 self.combined_access.write_all();
658 }
659
660 pub fn clear(&mut self) {
662 self.combined_access.clear();
663 self.filtered_accesses.clear();
664 }
665}
666
667impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
668 fn default() -> Self {
669 Self {
670 combined_access: Default::default(),
671 filtered_accesses: Vec::new(),
672 }
673 }
674}
675
676#[cfg(test)]
677mod tests {
678 use crate::query::access::AccessFilters;
679 use crate::query::{Access, FilteredAccess, FilteredAccessSet};
680 use fixedbitset::FixedBitSet;
681 use std::marker::PhantomData;
682
683 #[test]
684 fn read_all_access_conflicts() {
685 let mut access_a = Access::<usize>::default();
687 access_a.add_write(0);
688
689 let mut access_b = Access::<usize>::default();
690 access_b.read_all();
691
692 assert!(!access_b.is_compatible(&access_a));
693
694 let mut access_a = Access::<usize>::default();
696 access_a.read_all();
697
698 let mut access_b = Access::<usize>::default();
699 access_b.read_all();
700
701 assert!(access_b.is_compatible(&access_a));
702 }
703
704 #[test]
705 fn access_get_conflicts() {
706 let mut access_a = Access::<usize>::default();
707 access_a.add_read(0);
708 access_a.add_read(1);
709
710 let mut access_b = Access::<usize>::default();
711 access_b.add_read(0);
712 access_b.add_write(1);
713
714 assert_eq!(access_a.get_conflicts(&access_b), vec![1]);
715
716 let mut access_c = Access::<usize>::default();
717 access_c.add_write(0);
718 access_c.add_write(1);
719
720 assert_eq!(access_a.get_conflicts(&access_c), vec![0, 1]);
721 assert_eq!(access_b.get_conflicts(&access_c), vec![0, 1]);
722
723 let mut access_d = Access::<usize>::default();
724 access_d.add_read(0);
725
726 assert_eq!(access_d.get_conflicts(&access_a), vec![]);
727 assert_eq!(access_d.get_conflicts(&access_b), vec![]);
728 assert_eq!(access_d.get_conflicts(&access_c), vec![0]);
729 }
730
731 #[test]
732 fn filtered_combined_access() {
733 let mut access_a = FilteredAccessSet::<usize>::default();
734 access_a.add_unfiltered_read(1);
735
736 let mut filter_b = FilteredAccess::<usize>::default();
737 filter_b.add_write(1);
738
739 let conflicts = access_a.get_conflicts_single(&filter_b);
740 assert_eq!(
741 &conflicts,
742 &[1_usize],
743 "access_a: {access_a:?}, filter_b: {filter_b:?}"
744 );
745 }
746
747 #[test]
748 fn filtered_access_extend() {
749 let mut access_a = FilteredAccess::<usize>::default();
750 access_a.add_read(0);
751 access_a.add_read(1);
752 access_a.and_with(2);
753
754 let mut access_b = FilteredAccess::<usize>::default();
755 access_b.add_read(0);
756 access_b.add_write(3);
757 access_b.and_without(4);
758
759 access_a.extend(&access_b);
760
761 let mut expected = FilteredAccess::<usize>::default();
762 expected.add_read(0);
763 expected.add_read(1);
764 expected.and_with(2);
765 expected.add_write(3);
766 expected.and_without(4);
767
768 assert!(access_a.eq(&expected));
769 }
770
771 #[test]
772 fn filtered_access_extend_or() {
773 let mut access_a = FilteredAccess::<usize>::default();
774 access_a.add_write(0);
776 access_a.add_write(1);
777
778 let mut access_b = FilteredAccess::<usize>::default();
780 access_b.and_with(2);
781
782 let mut access_c = FilteredAccess::<usize>::default();
784 access_c.and_with(3);
785 access_c.and_without(4);
786
787 access_b.append_or(&access_c);
789 access_a.extend(&access_b);
792
793 let mut expected = FilteredAccess::<usize>::default();
797 expected.add_write(0);
798 expected.add_write(1);
799 expected.filter_sets = vec![
801 AccessFilters {
802 with: FixedBitSet::with_capacity_and_blocks(3, [0b111]),
803 without: FixedBitSet::default(),
804 _index_type: PhantomData,
805 },
806 AccessFilters {
807 with: FixedBitSet::with_capacity_and_blocks(4, [0b1011]),
808 without: FixedBitSet::with_capacity_and_blocks(5, [0b10000]),
809 _index_type: PhantomData,
810 },
811 ];
812
813 assert_eq!(access_a, expected);
814 }
815}