bevy_ecs/query/
access.rs

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
8/// A wrapper struct to make Debug representations of [`FixedBitSet`] easier
9/// to read, when used to store [`SparseSetIndex`].
10///
11/// Instead of the raw integer representation of the `FixedBitSet`, the list of
12/// `T` valid for [`SparseSetIndex`] is shown.
13///
14/// Normal `FixedBitSet` `Debug` output:
15/// ```text
16/// read_and_writes: FixedBitSet { data: [ 160 ], length: 8 }
17/// ```
18///
19/// Which, unless you are a computer, doesn't help much understand what's in
20/// the set. With `FormattedBitSet`, we convert the present set entries into
21/// what they stand for, it is much clearer what is going on:
22/// ```text
23/// read_and_writes: [ ComponentId(5), ComponentId(7) ]
24/// ```
25struct 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/// Tracks read and write access to specific elements in a collection.
48///
49/// Used internally to ensure soundness during system initialization and execution.
50/// See the [`is_compatible`](Access::is_compatible) and [`get_conflicts`](Access::get_conflicts) functions.
51#[derive(Eq, PartialEq)]
52pub struct Access<T: SparseSetIndex> {
53    /// All accessed components, or forbidden components if
54    /// `Self::component_read_and_writes_inverted` is set.
55    component_read_and_writes: FixedBitSet,
56    /// All exclusively-accessed components, or components that may not be
57    /// exclusively accessed if `Self::component_writes_inverted` is set.
58    component_writes: FixedBitSet,
59    /// All accessed resources.
60    resource_read_and_writes: FixedBitSet,
61    /// The exclusively-accessed resources.
62    resource_writes: FixedBitSet,
63    /// Is `true` if this component can read all components *except* those
64    /// present in `Self::component_read_and_writes`.
65    component_read_and_writes_inverted: bool,
66    /// Is `true` if this component can write to all components *except* those
67    /// present in `Self::component_writes`.
68    component_writes_inverted: bool,
69    /// Is `true` if this has access to all resources.
70    /// This field is a performance optimization for `&World` (also harder to mess up for soundness).
71    reads_all_resources: bool,
72    /// Is `true` if this has mutable access to all resources.
73    /// If this is true, then `reads_all` must also be true.
74    writes_all_resources: bool,
75    // Components that are not accessed, but whose presence in an archetype affect query results.
76    archetypal: FixedBitSet,
77    marker: PhantomData<T>,
78}
79
80// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
81impl<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    /// Creates an empty [`Access`] collection.
151    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    /// Adds access to the component given by `index`.
183    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    /// Adds exclusive access to the component given by `index`.
189    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    /// Adds access to the resource given by `index`.
196    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    /// Adds exclusive access to the resource given by `index`.
202    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    /// Removes both read and write access to the component given by `index`.
226    ///
227    /// Because this method corresponds to the set difference operator ∖, it can
228    /// create complicated logical formulas that you should verify correctness
229    /// of. For example, A ∪ (B ∖ A) isn't equivalent to (A ∪ B) ∖ A, so you
230    /// can't replace a call to `remove_component_read` followed by a call to
231    /// `extend` with a call to `extend` followed by a call to
232    /// `remove_component_read`.
233    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    /// Removes write access to the component given by `index`.
240    ///
241    /// Because this method corresponds to the set difference operator ∖, it can
242    /// create complicated logical formulas that you should verify correctness
243    /// of. For example, A ∪ (B ∖ A) isn't equivalent to (A ∪ B) ∖ A, so you
244    /// can't replace a call to `remove_component_write` followed by a call to
245    /// `extend` with a call to `extend` followed by a call to
246    /// `remove_component_write`.
247    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    /// Adds an archetypal (indirect) access to the component given by `index`.
253    ///
254    /// This is for components whose values are not accessed (and thus will never cause conflicts),
255    /// but whose presence in an archetype may affect query results.
256    ///
257    /// Currently, this is only used for [`Has<T>`].
258    ///
259    /// [`Has<T>`]: crate::query::Has
260    pub fn add_archetypal(&mut self, index: T) {
261        self.archetypal.grow_and_insert(index.sparse_set_index());
262    }
263
264    /// Returns `true` if this can access the component given by `index`.
265    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    /// Returns `true` if this can access any component.
273    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    /// Returns `true` if this can exclusively access the component given by `index`.
278    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    /// Returns `true` if this accesses any component mutably.
283    pub fn has_any_component_write(&self) -> bool {
284        self.component_writes_inverted || !self.component_writes.is_clear()
285    }
286
287    /// Returns `true` if this can access the resource given by `index`.
288    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    /// Returns `true` if this can access any resource.
296    pub fn has_any_resource_read(&self) -> bool {
297        self.reads_all_resources || !self.resource_read_and_writes.is_clear()
298    }
299
300    /// Returns `true` if this can exclusively access the resource given by `index`.
301    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    /// Returns `true` if this accesses any resource mutably.
306    pub fn has_any_resource_write(&self) -> bool {
307        self.writes_all_resources || !self.resource_writes.is_clear()
308    }
309
310    /// Returns true if this has an archetypal (indirect) access to the component given by `index`.
311    ///
312    /// This is a component whose value is not accessed (and thus will never cause conflicts),
313    /// but whose presence in an archetype may affect query results.
314    ///
315    /// Currently, this is only used for [`Has<T>`].
316    ///
317    /// [`Has<T>`]: crate::query::Has
318    pub fn has_archetypal(&self, index: T) -> bool {
319        self.archetypal.contains(index.sparse_set_index())
320    }
321
322    /// Sets this as having access to all components (i.e. `EntityRef`).
323    #[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    /// Sets this as having mutable access to all components (i.e. `EntityMut`).
330    #[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    /// Sets this as having access to all resources (i.e. `&World`).
338    #[inline]
339    pub fn read_all_resources(&mut self) {
340        self.reads_all_resources = true;
341    }
342
343    /// Sets this as having mutable access to all resources (i.e. `&mut World`).
344    #[inline]
345    pub fn write_all_resources(&mut self) {
346        self.reads_all_resources = true;
347        self.writes_all_resources = true;
348    }
349
350    /// Sets this as having access to all indexed elements (i.e. `&World`).
351    #[inline]
352    pub fn read_all(&mut self) {
353        self.read_all_components();
354        self.read_all_resources();
355    }
356
357    /// Sets this as having mutable access to all indexed elements (i.e. `&mut World`).
358    #[inline]
359    pub fn write_all(&mut self) {
360        self.write_all_components();
361        self.write_all_resources();
362    }
363
364    /// Returns `true` if this has access to all components (i.e. `EntityRef`).
365    #[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    /// Returns `true` if this has write access to all components (i.e. `EntityMut`).
371    #[inline]
372    pub fn has_write_all_components(&self) -> bool {
373        self.component_writes_inverted && self.component_writes.is_clear()
374    }
375
376    /// Returns `true` if this has access to all resources (i.e. `EntityRef`).
377    #[inline]
378    pub fn has_read_all_resources(&self) -> bool {
379        self.reads_all_resources
380    }
381
382    /// Returns `true` if this has write access to all resources (i.e. `EntityMut`).
383    #[inline]
384    pub fn has_write_all_resources(&self) -> bool {
385        self.writes_all_resources
386    }
387
388    /// Returns `true` if this has access to all indexed elements (i.e. `&World`).
389    pub fn has_read_all(&self) -> bool {
390        self.has_read_all_components() && self.has_read_all_resources()
391    }
392
393    /// Returns `true` if this has write access to all indexed elements (i.e. `&mut World`).
394    pub fn has_write_all(&self) -> bool {
395        self.has_write_all_components() && self.has_write_all_resources()
396    }
397
398    /// Removes all writes.
399    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    /// Removes all accesses.
407    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    /// Adds all access from `other`.
419    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                // We have to grow here because the new bits are going to get flipped to 1.
439                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                // We have to grow here because the new bits are going to get flipped to 1.
468                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    /// Returns `true` if the access and `other` can be active at the same time,
492    /// only looking at their component access.
493    ///
494    /// [`Access`] instances are incompatible if one can write
495    /// an element that the other can read or write.
496    pub fn is_components_compatible(&self, other: &Access<T>) -> bool {
497        // We have a conflict if we write and they read or write, or if they
498        // write and we read or write.
499        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    /// Returns `true` if the access and `other` can be active at the same time,
542    /// only looking at their resource access.
543    ///
544    /// [`Access`] instances are incompatible if one can write
545    /// an element that the other can read or write.
546    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    /// Returns `true` if the access and `other` can be active at the same time.
571    ///
572    /// [`Access`] instances are incompatible if one can write
573    /// an element that the other can read or write.
574    pub fn is_compatible(&self, other: &Access<T>) -> bool {
575        self.is_components_compatible(other) && self.is_resources_compatible(other)
576    }
577
578    /// Returns `true` if the set's component access is a subset of another, i.e. `other`'s component access
579    /// contains at least all the values in `self`.
580    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    /// Returns `true` if the set's resource access is a subset of another, i.e. `other`'s resource access
626    /// contains at least all the values in `self`.
627    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    /// Returns `true` if the set is a subset of another, i.e. `other` contains
650    /// at least all the values in `self`.
651    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        // We have a conflict if we write and they read or write, or if they
659        // write and we read or write.
660        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            // There's no way that I can see to do this without a temporary.
680            // Neither CNF nor DNF allows us to avoid one.
681            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    /// Returns a vector of elements that the access and `other` cannot access at the same time.
695    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    /// Returns the indices of the resources this has access to.
734    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    /// Returns the indices of the resources this has non-exclusive access to.
741    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    /// Returns the indices of the resources this has exclusive access to.
748    pub fn resource_writes(&self) -> impl Iterator<Item = T> + '_ {
749        self.resource_writes.ones().map(T::get_sparse_set_index)
750    }
751
752    /// Returns the indices of the components that this has an archetypal access to.
753    ///
754    /// These are components whose values are not accessed (and thus will never cause conflicts),
755    /// but whose presence in an archetype may affect query results.
756    ///
757    /// Currently, this is only used for [`Has<T>`].
758    ///
759    /// [`Has<T>`]: crate::query::Has
760    pub fn archetypal(&self) -> impl Iterator<Item = T> + '_ {
761        self.archetypal.ones().map(T::get_sparse_set_index)
762    }
763
764    /// Returns an iterator over the component IDs that this `Access` either
765    /// reads and writes or can't read or write.
766    ///
767    /// The returned flag specifies whether the list consists of the components
768    /// that the access *can* read or write (false) or whether the list consists
769    /// of the components that the access *can't* read or write (true).
770    ///
771    /// Because this method depends on internal implementation details of
772    /// `Access`, it's not recommended. Prefer to manage your own lists of
773    /// accessible components if your application needs to do that.
774    #[doc(hidden)]
775    // TODO: this should be deprecated and removed, see https://github.com/bevyengine/bevy/issues/16339
776    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    /// Returns an iterator over the component IDs that this `Access` either
786    /// writes or can't write.
787    ///
788    /// The returned flag specifies whether the list consists of the components
789    /// that the access *can* write (false) or whether the list consists of the
790    /// components that the access *can't* write (true).
791    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/// An [`Access`] that has been filtered to include and exclude certain combinations of elements.
800///
801/// Used internally to statically check if queries are disjoint.
802///
803/// Subtle: a `read` or `write` in `access` should not be considered to imply a
804/// `with` access.
805///
806/// For example consider `Query<Option<&T>>` this only has a `read` of `T` as doing
807/// otherwise would allow for queries to be considered disjoint when they shouldn't:
808/// - `Query<(&mut T, Option<&U>)>` read/write `T`, read `U`, with `U`
809/// - `Query<&mut T, Without<U>>` read/write `T`, without `U`
810///     from this we could reasonably conclude that the queries are disjoint but they aren't.
811///
812/// In order to solve this the actual access that `Query<(&mut T, Option<&U>)>` has
813/// is read/write `T`, read `U`. It must still have a read `U` access otherwise the following
814/// queries would be incorrectly considered disjoint:
815/// - `Query<&mut T>`  read/write `T`
816/// - `Query<Option<&T>>` accesses nothing
817///
818/// See comments the [`WorldQuery`](super::WorldQuery) impls of [`AnyOf`](super::AnyOf)/`Option`/[`Or`](super::Or) for more information.
819#[derive(Debug, Eq, PartialEq)]
820pub struct FilteredAccess<T: SparseSetIndex> {
821    pub(crate) access: Access<T>,
822    pub(crate) required: FixedBitSet,
823    // An array of filter sets to express `With` or `Without` clauses in disjunctive normal form, for example: `Or<(With<A>, With<B>)>`.
824    // Filters like `(With<A>, Or<(With<B>, Without<C>)>` are expanded into `Or<((With<A>, With<B>), (With<A>, Without<C>))>`.
825    pub(crate) filter_sets: Vec<AccessFilters<T>>,
826}
827
828// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
829impl<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/// Records how two accesses conflict with each other
860#[derive(Debug, PartialEq, From)]
861pub enum AccessConflicts {
862    /// Conflict is for all indices
863    All,
864    /// There is a conflict for a subset of indices
865    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    /// An [`AccessConflicts`] which represents the absence of any conflict
907    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    /// Returns a `FilteredAccess` which has no access and matches everything.
920    /// This is the equivalent of a `TRUE` logic atom.
921    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    /// Returns a `FilteredAccess` which has no access and matches nothing.
930    /// This is the equivalent of a `FALSE` logic atom.
931    pub fn matches_nothing() -> Self {
932        Self {
933            access: Access::default(),
934            required: FixedBitSet::default(),
935            filter_sets: Vec::new(),
936        }
937    }
938
939    /// Returns a reference to the underlying unfiltered access.
940    #[inline]
941    pub fn access(&self) -> &Access<T> {
942        &self.access
943    }
944
945    /// Returns a mutable reference to the underlying unfiltered access.
946    #[inline]
947    pub fn access_mut(&mut self) -> &mut Access<T> {
948        &mut self.access
949    }
950
951    /// Adds access to the component given by `index`.
952    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    /// Adds exclusive access to the component given by `index`.
959    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    /// Adds access to the resource given by `index`.
966    pub fn add_resource_read(&mut self, index: T) {
967        self.access.add_resource_read(index.clone());
968    }
969
970    /// Adds exclusive access to the resource given by `index`.
971    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    /// Adds a `With` filter: corresponds to a conjunction (AND) operation.
980    ///
981    /// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
982    /// Adding `AND With<C>` via this method transforms it into the equivalent of  `Or<((With<A>, With<C>), (With<B>, With<C>))>`.
983    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    /// Adds a `Without` filter: corresponds to a conjunction (AND) operation.
990    ///
991    /// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
992    /// Adding `AND Without<C>` via this method transforms it into the equivalent of  `Or<((With<A>, Without<C>), (With<B>, Without<C>))>`.
993    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    /// Appends an array of filters: corresponds to a disjunction (OR) operation.
1000    ///
1001    /// As the underlying array of filters represents a disjunction,
1002    /// where each element (`AccessFilters`) represents a conjunction,
1003    /// we can simply append to the array.
1004    pub fn append_or(&mut self, other: &FilteredAccess<T>) {
1005        self.filter_sets.append(&mut other.filter_sets.clone());
1006    }
1007
1008    /// Adds all of the accesses from `other` to `self`.
1009    pub fn extend_access(&mut self, other: &FilteredAccess<T>) {
1010        self.access.extend(&other.access);
1011    }
1012
1013    /// Returns `true` if this and `other` can be active at the same time.
1014    pub fn is_compatible(&self, other: &FilteredAccess<T>) -> bool {
1015        if self.access.is_compatible(&other.access) {
1016            return true;
1017        }
1018
1019        // If the access instances are incompatible, we want to check that whether filters can
1020        // guarantee that queries are disjoint.
1021        // Since the `filter_sets` array represents a Disjunctive Normal Form formula ("ORs of ANDs"),
1022        // we need to make sure that each filter set (ANDs) rule out every filter set from the `other` instance.
1023        //
1024        // For example, `Query<&mut C, Or<(With<A>, Without<B>)>>` is compatible `Query<&mut C, (With<B>, Without<A>)>`,
1025        // but `Query<&mut C, Or<(Without<A>, Without<B>)>>` isn't compatible with `Query<&mut C, Or<(With<A>, With<B>)>>`.
1026        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    /// Returns a vector of elements that this and `other` cannot access at the same time.
1035    pub fn get_conflicts(&self, other: &FilteredAccess<T>) -> AccessConflicts {
1036        if !self.is_compatible(other) {
1037            // filters are disjoint, so we can just look at the unfiltered intersection
1038            return self.access.get_conflicts(&other.access);
1039        }
1040        AccessConflicts::empty()
1041    }
1042
1043    /// Adds all access and filters from `other`.
1044    ///
1045    /// Corresponds to a conjunction operation (AND) for filters.
1046    ///
1047    /// Extending `Or<(With<A>, Without<B>)>` with `Or<(With<C>, Without<D>)>` will result in
1048    /// `Or<((With<A>, With<C>), (With<A>, Without<D>), (Without<B>, With<C>), (Without<B>, Without<D>))>`.
1049    pub fn extend(&mut self, other: &FilteredAccess<T>) {
1050        self.access.extend(&other.access);
1051        self.required.union_with(&other.required);
1052
1053        // We can avoid allocating a new array of bitsets if `other` contains just a single set of filters:
1054        // in this case we can short-circuit by performing an in-place union for each bitset.
1055        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    /// Sets the underlying unfiltered access as having access to all indexed elements.
1076    pub fn read_all(&mut self) {
1077        self.access.read_all();
1078    }
1079
1080    /// Sets the underlying unfiltered access as having mutable access to all indexed elements.
1081    pub fn write_all(&mut self) {
1082        self.access.write_all();
1083    }
1084
1085    /// Sets the underlying unfiltered access as having access to all components.
1086    pub fn read_all_components(&mut self) {
1087        self.access.read_all_components();
1088    }
1089
1090    /// Sets the underlying unfiltered access as having mutable access to all components.
1091    pub fn write_all_components(&mut self) {
1092        self.access.write_all_components();
1093    }
1094
1095    /// Returns `true` if the set is a subset of another, i.e. `other` contains
1096    /// at least all the values in `self`.
1097    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    /// Returns the indices of the elements that this access filters for.
1102    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    /// Returns the indices of the elements that this access filters out.
1109    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
1123// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
1124impl<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        // Although not technically complete, we don't consider the case when `AccessFilters`'s
1161        // `without` bitset contradicts its own `with` bitset (e.g. `(With<A>, Without<A>)`).
1162        // Such query would be considered compatible with any other query, but as it's almost
1163        // always an error, we ignore this case instead of treating such query as compatible
1164        // with others.
1165        !self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
1166    }
1167}
1168
1169/// A collection of [`FilteredAccess`] instances.
1170///
1171/// Used internally to statically check if systems have conflicting access.
1172///
1173/// It stores multiple sets of accesses.
1174/// - A "combined" set, which is the access of all filters in this set combined.
1175/// - The set of access of each individual filters in this set.
1176#[derive(Debug, PartialEq, Eq)]
1177pub struct FilteredAccessSet<T: SparseSetIndex> {
1178    combined_access: Access<T>,
1179    filtered_accesses: Vec<FilteredAccess<T>>,
1180}
1181
1182// This is needed since `#[derive(Clone)]` does not generate optimized `clone_from`.
1183impl<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    /// Returns a reference to the unfiltered access of the entire set.
1199    #[inline]
1200    pub fn combined_access(&self) -> &Access<T> {
1201        &self.combined_access
1202    }
1203
1204    /// Returns `true` if this and `other` can be active at the same time.
1205    ///
1206    /// Access conflict resolution happen in two steps:
1207    /// 1. A "coarse" check, if there is no mutual unfiltered conflict between
1208    ///    `self` and `other`, we already know that the two access sets are
1209    ///    compatible.
1210    /// 2. A "fine grained" check, it kicks in when the "coarse" check fails.
1211    ///    the two access sets might still be compatible if some of the accesses
1212    ///    are restricted with the [`With`](super::With) or [`Without`](super::Without) filters so that access is
1213    ///    mutually exclusive. The fine grained phase iterates over all filters in
1214    ///    the `self` set and compares it to all the filters in the `other` set,
1215    ///    making sure they are all mutually compatible.
1216    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    /// Returns a vector of elements that this set and `other` cannot access at the same time.
1231    pub fn get_conflicts(&self, other: &FilteredAccessSet<T>) -> AccessConflicts {
1232        // if the unfiltered access is incompatible, must check each pair
1233        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    /// Returns a vector of elements that this set and `other` cannot access at the same time.
1245    pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess<T>) -> AccessConflicts {
1246        // if the unfiltered access is incompatible, must check each pair
1247        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    /// Adds the filtered access to the set.
1257    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    /// Adds a read access to a resource to the set.
1263    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    /// Adds a write access to a resource to the set.
1270    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    /// Adds read access to all resources to the set.
1277    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    /// Adds write access to all resources to the set.
1284    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    /// Adds all of the accesses from the passed set to `self`.
1291    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    /// Marks the set as reading all possible indices of type T.
1299    pub fn read_all(&mut self) {
1300        self.combined_access.read_all();
1301    }
1302
1303    /// Marks the set as writing all T.
1304    pub fn write_all(&mut self) {
1305        self.combined_access.write_all();
1306    }
1307
1308    /// Removes all accesses stored in this set.
1309    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        // read_all / single write
1465        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        // read_all / read_all
1474        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        // Exclusive access to `(&mut A, &mut B)`.
1560        access_a.add_component_write(0);
1561        access_a.add_component_write(1);
1562
1563        // Filter by `With<C>`.
1564        let mut access_b = FilteredAccess::<usize>::default();
1565        access_b.and_with(2);
1566
1567        // Filter by `(With<D>, Without<E>)`.
1568        let mut access_c = FilteredAccess::<usize>::default();
1569        access_c.and_with(3);
1570        access_c.and_without(4);
1571
1572        // Turns `access_b` into `Or<(With<C>, (With<D>, Without<D>))>`.
1573        access_b.append_or(&access_c);
1574        // Applies the filters to the initial query, which corresponds to the FilteredAccess'
1575        // representation of `Query<(&mut A, &mut B), Or<(With<C>, (With<D>, Without<E>))>>`.
1576        access_a.extend(&access_b);
1577
1578        // Construct the expected `FilteredAccess` struct.
1579        // The intention here is to test that exclusive access implied by `add_write`
1580        // forms correct normalized access structs when extended with `Or` filters.
1581        let mut expected = FilteredAccess::<usize>::default();
1582        expected.add_component_write(0);
1583        expected.add_component_write(1);
1584        // The resulted access is expected to represent `Or<((With<A>, With<B>, With<C>), (With<A>, With<B>, With<D>, Without<E>))>`.
1585        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}