@@ -431,78 +431,58 @@ impl<T: SparseSetIndex> Access<T> {
431
431
432
432
/// Adds all access from `other`.
433
433
pub fn extend ( & mut self , other : & Access < T > ) {
434
- let component_read_and_writes_inverted =
435
- self . component_read_and_writes_inverted || other. component_read_and_writes_inverted ;
436
- let component_writes_inverted =
437
- self . component_writes_inverted || other. component_writes_inverted ;
438
-
439
- match (
440
- self . component_read_and_writes_inverted ,
434
+ invertible_union_with (
435
+ & mut self . component_read_and_writes ,
436
+ & mut self . component_read_and_writes_inverted ,
437
+ & other. component_read_and_writes ,
441
438
other. component_read_and_writes_inverted ,
442
- ) {
443
- ( true , true ) => {
444
- self . component_read_and_writes
445
- . intersect_with ( & other. component_read_and_writes ) ;
446
- }
447
- ( true , false ) => {
448
- self . component_read_and_writes
449
- . difference_with ( & other. component_read_and_writes ) ;
450
- }
451
- ( false , true ) => {
452
- // We have to grow here because the new bits are going to get flipped to 1.
453
- self . component_read_and_writes . grow (
454
- self . component_read_and_writes
455
- . len ( )
456
- . max ( other. component_read_and_writes . len ( ) ) ,
457
- ) ;
458
- self . component_read_and_writes . toggle_range ( ..) ;
459
- self . component_read_and_writes
460
- . intersect_with ( & other. component_read_and_writes ) ;
461
- }
462
- ( false , false ) => {
463
- self . component_read_and_writes
464
- . union_with ( & other. component_read_and_writes ) ;
465
- }
466
- }
467
-
468
- match (
469
- self . component_writes_inverted ,
439
+ ) ;
440
+ invertible_union_with (
441
+ & mut self . component_writes ,
442
+ & mut self . component_writes_inverted ,
443
+ & other. component_writes ,
470
444
other. component_writes_inverted ,
471
- ) {
472
- ( true , true ) => {
473
- self . component_writes
474
- . intersect_with ( & other. component_writes ) ;
475
- }
476
- ( true , false ) => {
477
- self . component_writes
478
- . difference_with ( & other. component_writes ) ;
479
- }
480
- ( false , true ) => {
481
- // We have to grow here because the new bits are going to get flipped to 1.
482
- self . component_writes . grow (
483
- self . component_writes
484
- . len ( )
485
- . max ( other. component_writes . len ( ) ) ,
486
- ) ;
487
- self . component_writes . toggle_range ( ..) ;
488
- self . component_writes
489
- . intersect_with ( & other. component_writes ) ;
490
- }
491
- ( false , false ) => {
492
- self . component_writes . union_with ( & other. component_writes ) ;
493
- }
494
- }
445
+ ) ;
495
446
496
447
self . reads_all_resources = self . reads_all_resources || other. reads_all_resources ;
497
448
self . writes_all_resources = self . writes_all_resources || other. writes_all_resources ;
498
- self . component_read_and_writes_inverted = component_read_and_writes_inverted;
499
- self . component_writes_inverted = component_writes_inverted;
500
449
self . resource_read_and_writes
501
450
. union_with ( & other. resource_read_and_writes ) ;
502
451
self . resource_writes . union_with ( & other. resource_writes ) ;
503
452
self . archetypal . union_with ( & other. archetypal ) ;
504
453
}
505
454
455
+ /// Removes any access from `self` that would conflict with `other`.
456
+ /// This removes any reads and writes for any component written by `other`,
457
+ /// and removes any writes for any component read by `other`.
458
+ pub fn remove_conflicting_access ( & mut self , other : & Access < T > ) {
459
+ invertible_difference_with (
460
+ & mut self . component_read_and_writes ,
461
+ & mut self . component_read_and_writes_inverted ,
462
+ & other. component_writes ,
463
+ other. component_writes_inverted ,
464
+ ) ;
465
+ invertible_difference_with (
466
+ & mut self . component_writes ,
467
+ & mut self . component_writes_inverted ,
468
+ & other. component_read_and_writes ,
469
+ other. component_read_and_writes_inverted ,
470
+ ) ;
471
+
472
+ if other. reads_all_resources {
473
+ self . writes_all_resources = false ;
474
+ self . resource_writes . clear ( ) ;
475
+ }
476
+ if other. writes_all_resources {
477
+ self . reads_all_resources = false ;
478
+ self . resource_read_and_writes . clear ( ) ;
479
+ }
480
+ self . resource_read_and_writes
481
+ . difference_with ( & other. resource_writes ) ;
482
+ self . resource_writes
483
+ . difference_with ( & other. resource_read_and_writes ) ;
484
+ }
485
+
506
486
/// Returns `true` if the access and `other` can be active at the same time,
507
487
/// only looking at their component access.
508
488
///
@@ -840,6 +820,55 @@ impl<T: SparseSetIndex> Access<T> {
840
820
}
841
821
}
842
822
823
+ /// Performs an in-place union of `other` into `self`, where either set may be inverted.
824
+ ///
825
+ /// Each set corresponds to a `FixedBitSet` if `inverted` is `false`,
826
+ /// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`.
827
+ ///
828
+ /// This updates the `self` set to include any elements in the `other` set.
829
+ /// Note that this may change `self_inverted` to `true` if we add an infinite
830
+ /// set to a finite one, resulting in a new infinite set.
831
+ fn invertible_union_with (
832
+ self_set : & mut FixedBitSet ,
833
+ self_inverted : & mut bool ,
834
+ other_set : & FixedBitSet ,
835
+ other_inverted : bool ,
836
+ ) {
837
+ match ( * self_inverted, other_inverted) {
838
+ ( true , true ) => self_set. intersect_with ( other_set) ,
839
+ ( true , false ) => self_set. difference_with ( other_set) ,
840
+ ( false , true ) => {
841
+ * self_inverted = true ;
842
+ // We have to grow here because the new bits are going to get flipped to 1.
843
+ self_set. grow ( other_set. len ( ) ) ;
844
+ self_set. toggle_range ( ..) ;
845
+ self_set. intersect_with ( other_set) ;
846
+ }
847
+ ( false , false ) => self_set. union_with ( other_set) ,
848
+ }
849
+ }
850
+
851
+ /// Performs an in-place set difference of `other` from `self`, where either set may be inverted.
852
+ ///
853
+ /// Each set corresponds to a `FixedBitSet` if `inverted` is `false`,
854
+ /// or to the infinite (co-finite) complement of the `FixedBitSet` if `inverted` is `true`.
855
+ ///
856
+ /// This updates the `self` set to remove any elements in the `other` set.
857
+ /// Note that this may change `self_inverted` to `false` if we remove an
858
+ /// infinite set from another infinite one, resulting in a finite difference.
859
+ fn invertible_difference_with (
860
+ self_set : & mut FixedBitSet ,
861
+ self_inverted : & mut bool ,
862
+ other_set : & FixedBitSet ,
863
+ other_inverted : bool ,
864
+ ) {
865
+ // We can share the implementation of `invertible_union_with` with some algebra:
866
+ // A - B = A & !B = !(!A | B)
867
+ * self_inverted = !* self_inverted;
868
+ invertible_union_with ( self_set, self_inverted, other_set, other_inverted) ;
869
+ * self_inverted = !* self_inverted;
870
+ }
871
+
843
872
/// Error returned when attempting to iterate over items included in an [`Access`]
844
873
/// if the access excludes items rather than including them.
845
874
#[ derive( Clone , Copy , PartialEq , Eq , Debug , Error ) ]
@@ -1428,6 +1457,7 @@ impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
1428
1457
1429
1458
#[ cfg( test) ]
1430
1459
mod tests {
1460
+ use super :: { invertible_difference_with, invertible_union_with} ;
1431
1461
use crate :: query:: {
1432
1462
access:: AccessFilters , Access , AccessConflicts , ComponentAccessKind , FilteredAccess ,
1433
1463
FilteredAccessSet , UnboundedAccessError ,
@@ -1770,4 +1800,99 @@ mod tests {
1770
1800
} ) ,
1771
1801
) ;
1772
1802
}
1803
+
1804
+ /// Create a `FixedBitSet` with a given number of total bits and a given list of bits to set.
1805
+ /// Setting the number of bits is important in tests since the `PartialEq` impl checks that the length matches.
1806
+ fn bit_set ( bits : usize , iter : impl IntoIterator < Item = usize > ) -> FixedBitSet {
1807
+ let mut result = FixedBitSet :: with_capacity ( bits) ;
1808
+ result. extend ( iter) ;
1809
+ result
1810
+ }
1811
+
1812
+ #[ test]
1813
+ fn invertible_union_with_tests ( ) {
1814
+ let invertible_union = |mut self_inverted : bool , other_inverted : bool | {
1815
+ // Check all four possible bit states: In both sets, the first, the second, or neither
1816
+ let mut self_set = bit_set ( 4 , [ 0 , 1 ] ) ;
1817
+ let other_set = bit_set ( 4 , [ 0 , 2 ] ) ;
1818
+ invertible_union_with (
1819
+ & mut self_set,
1820
+ & mut self_inverted,
1821
+ & other_set,
1822
+ other_inverted,
1823
+ ) ;
1824
+ ( self_set, self_inverted)
1825
+ } ;
1826
+
1827
+ // Check each combination of `inverted` flags
1828
+ let ( s, i) = invertible_union ( false , false ) ;
1829
+ // [0, 1] | [0, 2] = [0, 1, 2]
1830
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 0 , 1 , 2 ] ) , false ) ) ;
1831
+
1832
+ let ( s, i) = invertible_union ( false , true ) ;
1833
+ // [0, 1] | [1, 3, ...] = [0, 1, 3, ...]
1834
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 2 ] ) , true ) ) ;
1835
+
1836
+ let ( s, i) = invertible_union ( true , false ) ;
1837
+ // [2, 3, ...] | [0, 2] = [0, 2, 3, ...]
1838
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 1 ] ) , true ) ) ;
1839
+
1840
+ let ( s, i) = invertible_union ( true , true ) ;
1841
+ // [2, 3, ...] | [1, 3, ...] = [1, 2, 3, ...]
1842
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 0 ] ) , true ) ) ;
1843
+ }
1844
+
1845
+ #[ test]
1846
+ fn invertible_union_with_different_lengths ( ) {
1847
+ // When adding a large inverted set to a small normal set,
1848
+ // make sure we invert the bits beyond the original length.
1849
+ // Failing to call `grow` before `toggle_range` would cause bit 1 to be zero,
1850
+ // which would incorrectly treat it as included in the output set.
1851
+ let mut self_set = bit_set ( 1 , [ 0 ] ) ;
1852
+ let mut self_inverted = false ;
1853
+ let other_set = bit_set ( 3 , [ 0 , 1 ] ) ;
1854
+ let other_inverted = true ;
1855
+ invertible_union_with (
1856
+ & mut self_set,
1857
+ & mut self_inverted,
1858
+ & other_set,
1859
+ other_inverted,
1860
+ ) ;
1861
+
1862
+ // [0] | [2, ...] = [0, 2, ...]
1863
+ assert_eq ! ( ( self_set, self_inverted) , ( bit_set( 3 , [ 1 ] ) , true ) ) ;
1864
+ }
1865
+
1866
+ #[ test]
1867
+ fn invertible_difference_with_tests ( ) {
1868
+ let invertible_difference = |mut self_inverted : bool , other_inverted : bool | {
1869
+ // Check all four possible bit states: In both sets, the first, the second, or neither
1870
+ let mut self_set = bit_set ( 4 , [ 0 , 1 ] ) ;
1871
+ let other_set = bit_set ( 4 , [ 0 , 2 ] ) ;
1872
+ invertible_difference_with (
1873
+ & mut self_set,
1874
+ & mut self_inverted,
1875
+ & other_set,
1876
+ other_inverted,
1877
+ ) ;
1878
+ ( self_set, self_inverted)
1879
+ } ;
1880
+
1881
+ // Check each combination of `inverted` flags
1882
+ let ( s, i) = invertible_difference ( false , false ) ;
1883
+ // [0, 1] - [0, 2] = [1]
1884
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 1 ] ) , false ) ) ;
1885
+
1886
+ let ( s, i) = invertible_difference ( false , true ) ;
1887
+ // [0, 1] - [1, 3, ...] = [0]
1888
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 0 ] ) , false ) ) ;
1889
+
1890
+ let ( s, i) = invertible_difference ( true , false ) ;
1891
+ // [2, 3, ...] - [0, 2] = [3, ...]
1892
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 0 , 1 , 2 ] ) , true ) ) ;
1893
+
1894
+ let ( s, i) = invertible_difference ( true , true ) ;
1895
+ // [2, 3, ...] - [1, 3, ...] = [2]
1896
+ assert_eq ! ( ( s, i) , ( bit_set( 4 , [ 2 ] ) , false ) ) ;
1897
+ }
1773
1898
}
0 commit comments