use crate::world::unsafe_world_cell::UnsafeWorldCell;
use crate::{component::ComponentId, resource::IS_RESOURCE};
use alloc::{format, string::String, vec, vec::Vec};
use core::iter::FusedIterator;
use core::mem;
use core::{fmt, fmt::Debug};
use derive_more::From;
use fixedbitset::{Difference, FixedBitSet, Intersection, IntoOnes, Ones, Union};
use thiserror::Error;
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum InvertibleComponentIdSet {
Included(ComponentIdSet),
Excluded(ComponentIdSet),
}
impl Default for InvertibleComponentIdSet {
fn default() -> Self {
Self::new()
}
}
impl InvertibleComponentIdSet {
#[inline]
pub const fn new() -> Self {
Self::Included(ComponentIdSet::new())
}
#[inline]
pub const fn new_all() -> Self {
Self::Excluded(ComponentIdSet::new())
}
#[inline]
pub fn insert(&mut self, index: ComponentId) {
match self {
Self::Included(included) => included.insert(index),
Self::Excluded(excluded) => excluded.remove(index),
}
}
#[inline]
pub fn remove(&mut self, index: ComponentId) {
match self {
Self::Included(included) => included.remove(index),
Self::Excluded(excluded) => excluded.insert(index),
}
}
#[inline]
pub fn clear(&mut self) {
*self = Self::new();
}
#[inline]
pub fn all(&mut self) {
*self = Self::new_all();
}
#[inline]
pub fn contains(&self, index: ComponentId) -> bool {
match self {
Self::Included(included) => included.contains(index),
Self::Excluded(excluded) => !excluded.contains(index),
}
}
#[inline]
pub fn is_clear(&self) -> bool {
match self {
Self::Included(included) => included.is_clear(),
Self::Excluded(_) => false,
}
}
#[inline]
pub fn is_all(&self) -> bool {
match self {
Self::Included(_) => false,
Self::Excluded(excluded) => excluded.is_clear(),
}
}
#[inline]
pub fn is_unbounded(&self) -> bool {
match self {
Self::Included(_) => false,
Self::Excluded(_) => true,
}
}
#[inline]
pub fn into_finite_set(self) -> Option<ComponentIdSet> {
match self {
Self::Included(included) => Some(included),
Self::Excluded(_) => None,
}
}
#[inline]
pub fn as_finite_set(&self) -> Option<&ComponentIdSet> {
match self {
Self::Included(included) => Some(included),
Self::Excluded(_) => None,
}
}
#[inline]
pub fn as_exclusion_set(&self) -> Option<&ComponentIdSet> {
match self {
Self::Included(_) => None,
Self::Excluded(excluded) => Some(excluded),
}
}
pub fn union_with(&mut self, other: &Self) {
match (&mut *self, other) {
(Self::Included(this), Self::Included(other)) => this.union_with(other),
(Self::Included(this), Self::Excluded(other)) => {
this.difference_from(other);
*self = Self::Excluded(mem::take(this));
}
(Self::Excluded(this), Self::Included(other)) => this.difference_with(other),
(Self::Excluded(this), Self::Excluded(other)) => this.intersect_with(other),
}
}
pub fn union(&self, other: &Self) -> Self {
let mut result = self.clone();
result.union_with(other);
result
}
pub fn difference_with(&mut self, other: &Self) {
match (&mut *self, other) {
(Self::Included(this), Self::Included(other)) => this.difference_with(other),
(Self::Included(this), Self::Excluded(other)) => this.intersect_with(other),
(Self::Excluded(this), Self::Included(other)) => this.union_with(other),
(Self::Excluded(this), Self::Excluded(other)) => {
this.difference_from(other);
*self = Self::Included(mem::take(this));
}
}
}
pub fn difference(&self, other: &Self) -> Self {
let mut result = self.clone();
result.difference_with(other);
result
}
pub fn intersect_with(&mut self, other: &Self) {
match (&mut *self, other) {
(Self::Included(this), Self::Included(other)) => this.intersect_with(other),
(Self::Included(this), Self::Excluded(other)) => this.difference_with(other),
(Self::Excluded(this), Self::Included(other)) => {
this.difference_from(other);
*self = Self::Included(mem::take(this));
}
(Self::Excluded(this), Self::Excluded(other)) => this.union_with(other),
}
}
pub fn intersection(&self, other: &Self) -> Self {
let mut result = self.clone();
result.intersect_with(other);
result
}
pub fn is_disjoint(&self, other: &Self) -> bool {
match (self, other) {
(Self::Included(this), Self::Included(other)) => this.is_disjoint(other),
(Self::Included(this), Self::Excluded(other)) => this.is_subset(other),
(Self::Excluded(this), Self::Included(other)) => other.is_subset(this),
(Self::Excluded(_), Self::Excluded(_)) => false,
}
}
pub fn is_subset(&self, other: &Self) -> bool {
match (self, other) {
(Self::Included(this), Self::Included(other)) => this.is_subset(other),
(Self::Included(this), Self::Excluded(other)) => this.is_disjoint(other),
(Self::Excluded(_), Self::Included(_)) => false,
(Self::Excluded(this), Self::Excluded(other)) => other.is_subset(this),
}
}
}
#[derive(Eq, PartialEq, Default, Debug)]
pub struct Access {
reads: InvertibleComponentIdSet,
writes: InvertibleComponentIdSet,
archetypal: ComponentIdSet,
}
impl Clone for Access {
fn clone(&self) -> Self {
Self {
reads: self.reads.clone(),
writes: self.writes.clone(),
archetypal: self.archetypal.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.reads.clone_from(&source.reads);
self.writes.clone_from(&source.writes);
self.archetypal.clone_from(&source.archetypal);
}
}
impl Access {
pub const fn new() -> Self {
Self {
reads: InvertibleComponentIdSet::new(),
writes: InvertibleComponentIdSet::new(),
archetypal: ComponentIdSet::new(),
}
}
pub(crate) const fn new_read_all() -> Self {
Self {
reads: InvertibleComponentIdSet::new_all(),
writes: InvertibleComponentIdSet::new(),
archetypal: ComponentIdSet::new(),
}
}
pub(crate) const fn new_write_all() -> Self {
Self {
reads: InvertibleComponentIdSet::new_all(),
writes: InvertibleComponentIdSet::new_all(),
archetypal: ComponentIdSet::new(),
}
}
pub fn add_read(&mut self, index: ComponentId) {
self.reads.insert(index);
}
pub fn add_write(&mut self, index: ComponentId) {
self.reads.insert(index);
self.writes.insert(index);
}
pub fn remove_read(&mut self, index: ComponentId) {
self.writes.remove(index);
self.reads.remove(index);
}
pub fn remove_write(&mut self, index: ComponentId) {
self.writes.remove(index);
}
pub fn add_archetypal(&mut self, index: ComponentId) {
self.archetypal.insert(index);
}
pub fn has_read(&self, index: ComponentId) -> bool {
self.reads.contains(index)
}
pub fn has_any_read(&self) -> bool {
!self.reads.is_clear()
}
pub fn has_write(&self, index: ComponentId) -> bool {
self.writes.contains(index)
}
pub fn has_any_write(&self) -> bool {
!self.writes.is_clear()
}
pub fn has_archetypal(&self, index: ComponentId) -> bool {
self.archetypal.contains(index)
}
#[inline]
pub fn read_all(&mut self) {
self.reads.all();
}
#[inline]
pub fn write_all(&mut self) {
self.reads.all();
self.writes.all();
}
#[inline]
pub fn has_read_all(&self) -> bool {
self.reads.is_all()
}
#[inline]
pub fn has_write_all(&self) -> bool {
self.writes.is_all()
}
pub fn clear_writes(&mut self) {
self.writes.clear();
}
pub fn clear(&mut self) {
self.reads.clear();
self.writes.clear();
}
pub fn extend(&mut self, other: &Access) {
self.reads.union_with(&other.reads);
self.writes.union_with(&other.writes);
self.archetypal.union_with(&other.archetypal);
}
pub fn remove_conflicting_access(&mut self, other: &Access) {
self.reads.difference_with(&other.writes);
self.writes.difference_with(&other.reads);
}
pub fn is_compatible(&self, other: &Access) -> bool {
self.writes.is_disjoint(&other.reads) && other.writes.is_disjoint(&self.reads)
}
pub fn is_subset(&self, other: &Access) -> bool {
self.reads.is_subset(&other.reads) && self.writes.is_subset(&other.writes)
}
#[inline]
pub fn get_conflicts(&self, other: &Access) -> AccessConflicts {
let mut conflicts = self.writes.intersection(&other.reads);
conflicts.union_with(&other.writes.intersection(&self.reads));
conflicts
.into_finite_set()
.map_or(AccessConflicts::All, AccessConflicts::Individual)
}
pub fn archetypal(&self) -> &ComponentIdSet {
&self.archetypal
}
#[deprecated(since = "0.20.0", note = "use `reads_and_writes().as_finite_set()")]
pub fn try_reads_and_writes(&self) -> Result<&ComponentIdSet, UnboundedAccessError> {
self.reads.as_finite_set().ok_or(UnboundedAccessError {
writes_inverted: self.writes.is_unbounded(),
reads_inverted: self.reads.is_unbounded(),
})
}
pub fn reads(&self) -> &InvertibleComponentIdSet {
&self.reads
}
#[deprecated(since = "0.20.0", note = "use `writes().as_finite_set()")]
pub fn try_writes(&self) -> Result<&ComponentIdSet, UnboundedAccessError> {
self.writes.as_finite_set().ok_or(UnboundedAccessError {
writes_inverted: self.writes.is_unbounded(),
reads_inverted: self.reads.is_unbounded(),
})
}
pub fn writes(&self) -> &InvertibleComponentIdSet {
&self.writes
}
pub fn try_iter_access(
&self,
) -> Result<impl Iterator<Item = ComponentAccessKind> + '_, UnboundedAccessError> {
let reads = self.reads.as_finite_set().ok_or(UnboundedAccessError {
writes_inverted: self.writes.is_unbounded(),
reads_inverted: self.reads.is_unbounded(),
})?;
let accesses = reads.iter().map(|index| {
if self.writes.contains(index) {
ComponentAccessKind::Exclusive(index)
} else {
ComponentAccessKind::Shared(index)
}
});
let archetypal = self
.archetypal
.difference(reads)
.map(ComponentAccessKind::Archetypal);
Ok(accesses.chain(archetypal))
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
#[error("Access is unbounded")]
pub struct UnboundedAccessError {
pub writes_inverted: bool,
pub reads_inverted: bool,
}
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum ComponentAccessKind {
Archetypal(ComponentId),
Shared(ComponentId),
Exclusive(ComponentId),
}
impl ComponentAccessKind {
pub fn index(&self) -> &ComponentId {
let (Self::Archetypal(value) | Self::Shared(value) | Self::Exclusive(value)) = self;
value
}
}
#[derive(Debug, Eq, PartialEq)]
pub struct FilteredAccess {
pub(crate) access: Access,
pub(crate) required: ComponentIdSet,
pub(crate) filter_sets: Vec<AccessFilters>,
}
impl Clone for FilteredAccess {
fn clone(&self) -> Self {
Self {
access: self.access.clone(),
required: self.required.clone(),
filter_sets: self.filter_sets.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.access.clone_from(&source.access);
self.required.clone_from(&source.required);
self.filter_sets.clone_from(&source.filter_sets);
}
}
impl Default for FilteredAccess {
fn default() -> Self {
Self::matches_everything()
}
}
impl From<FilteredAccess> for FilteredAccessSet {
fn from(filtered_access: FilteredAccess) -> Self {
let mut base = FilteredAccessSet::default();
base.add(filtered_access);
base
}
}
#[derive(Debug, PartialEq, Eq, From)]
pub enum AccessConflicts {
All,
Individual(ComponentIdSet),
}
impl AccessConflicts {
fn add(&mut self, other: &Self) {
match (self, other) {
(s, AccessConflicts::All) => {
*s = AccessConflicts::All;
}
(AccessConflicts::Individual(this), AccessConflicts::Individual(other)) => {
this.extend(other);
}
_ => {}
}
}
pub fn is_empty(&self) -> bool {
match self {
Self::All => false,
Self::Individual(set) => set.is_clear(),
}
}
pub(crate) fn format_conflict_list(&self, world: UnsafeWorldCell) -> String {
match self {
AccessConflicts::All => String::new(),
AccessConflicts::Individual(indices) => indices
.iter()
.map(|index| {
format!(
"{}",
world.components().get_name(index).unwrap().shortname()
)
})
.collect::<Vec<_>>()
.join(", "),
}
}
pub(crate) fn empty() -> Self {
Self::Individual(ComponentIdSet::new())
}
}
impl From<Vec<ComponentId>> for AccessConflicts {
fn from(value: Vec<ComponentId>) -> Self {
Self::Individual(value.into_iter().collect())
}
}
impl FilteredAccess {
pub fn matches_everything() -> Self {
Self {
access: Access::default(),
required: ComponentIdSet::default(),
filter_sets: vec![AccessFilters::default()],
}
}
pub fn matches_nothing() -> Self {
Self {
access: Access::default(),
required: ComponentIdSet::default(),
filter_sets: Vec::new(),
}
}
#[inline]
pub fn access(&self) -> &Access {
&self.access
}
#[inline]
pub fn access_mut(&mut self) -> &mut Access {
&mut self.access
}
pub fn add_read(&mut self, index: ComponentId) {
self.access.add_read(index);
self.add_required(index);
self.and_with(index);
}
pub fn add_write(&mut self, index: ComponentId) {
self.access.add_write(index);
self.add_required(index);
self.and_with(index);
}
fn add_required(&mut self, index: ComponentId) {
self.required.insert(index);
}
pub fn and_with(&mut self, index: ComponentId) {
for filter in &mut self.filter_sets {
filter.with.insert(index);
}
}
pub fn and_without(&mut self, index: ComponentId) {
for filter in &mut self.filter_sets {
filter.without.insert(index);
}
}
pub fn append_or(&mut self, other: &FilteredAccess) {
self.filter_sets.append(&mut other.filter_sets.clone());
}
pub fn extend_access(&mut self, other: &FilteredAccess) {
self.access.extend(&other.access);
}
pub fn is_compatible(&self, other: &FilteredAccess) -> bool {
if self.access.is_compatible(&other.access) {
return true;
}
self.filter_sets.iter().all(|filter| {
other
.filter_sets
.iter()
.all(|other_filter| filter.is_ruled_out_by(other_filter))
})
}
pub fn get_conflicts(&self, other: &FilteredAccess) -> AccessConflicts {
if !self.is_compatible(other) {
return self.access.get_conflicts(&other.access);
}
AccessConflicts::empty()
}
pub fn extend(&mut self, other: &FilteredAccess) {
self.access.extend(&other.access);
self.required.union_with(&other.required);
if other.filter_sets.len() == 1 {
for filter in &mut self.filter_sets {
filter.with.union_with(&other.filter_sets[0].with);
filter.without.union_with(&other.filter_sets[0].without);
}
return;
}
let mut new_filters = Vec::with_capacity(self.filter_sets.len() * other.filter_sets.len());
for filter in &self.filter_sets {
for other_filter in &other.filter_sets {
let mut new_filter = filter.clone();
new_filter.with.union_with(&other_filter.with);
new_filter.without.union_with(&other_filter.without);
new_filters.push(new_filter);
}
}
self.filter_sets = new_filters;
}
pub fn read_all(&mut self) {
self.access.read_all();
}
pub fn write_all(&mut self) {
self.access.write_all();
}
pub fn is_subset(&self, other: &FilteredAccess) -> bool {
self.required.is_subset(&other.required) && self.access().is_subset(other.access())
}
pub fn required(&self) -> &ComponentIdSet {
&self.required
}
pub fn filter_sets(&self) -> &[AccessFilters] {
&self.filter_sets
}
pub fn with_filters(&self) -> impl Iterator<Item = ComponentId> + '_ {
self.filter_sets.iter().flat_map(|f| f.with.iter())
}
pub fn without_filters(&self) -> impl Iterator<Item = ComponentId> + '_ {
self.filter_sets.iter().flat_map(|f| f.without.iter())
}
pub fn contains(&self, index: ComponentId) -> bool {
self.access().has_archetypal(index)
|| self
.filter_sets
.iter()
.any(|f| f.with.contains(index) || f.without.contains(index))
}
}
#[derive(Eq, PartialEq, Default, Debug)]
pub struct AccessFilters {
pub(crate) with: ComponentIdSet,
pub(crate) without: ComponentIdSet,
}
impl Clone for AccessFilters {
fn clone(&self) -> Self {
Self {
with: self.with.clone(),
without: self.without.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.with.clone_from(&source.with);
self.without.clone_from(&source.without);
}
}
impl AccessFilters {
pub fn with(&self) -> &ComponentIdSet {
&self.with
}
pub fn without(&self) -> &ComponentIdSet {
&self.without
}
fn is_ruled_out_by(&self, other: &Self) -> bool {
!self.with.is_disjoint(&other.without) || !self.without.is_disjoint(&other.with)
}
}
#[derive(Debug, PartialEq, Eq, Default)]
pub struct FilteredAccessSet {
combined_access: Access,
filtered_accesses: Vec<FilteredAccess>,
}
impl Clone for FilteredAccessSet {
fn clone(&self) -> Self {
Self {
combined_access: self.combined_access.clone(),
filtered_accesses: self.filtered_accesses.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.combined_access.clone_from(&source.combined_access);
self.filtered_accesses.clone_from(&source.filtered_accesses);
}
}
impl FilteredAccessSet {
pub const fn new() -> Self {
Self {
combined_access: Access::new(),
filtered_accesses: Vec::new(),
}
}
#[inline]
pub fn combined_access(&self) -> &Access {
&self.combined_access
}
#[inline]
pub fn filtered_accesses(&self) -> &[FilteredAccess] {
&self.filtered_accesses
}
pub fn is_compatible(&self, other: &FilteredAccessSet) -> bool {
if self.combined_access.is_compatible(other.combined_access()) {
return true;
}
for filtered in &self.filtered_accesses {
for other_filtered in &other.filtered_accesses {
if !filtered.is_compatible(other_filtered) {
return false;
}
}
}
true
}
pub fn get_conflicts(&self, other: &FilteredAccessSet) -> AccessConflicts {
let mut conflicts = AccessConflicts::empty();
if !self.combined_access.is_compatible(other.combined_access()) {
for filtered in &self.filtered_accesses {
for other_filtered in &other.filtered_accesses {
conflicts.add(&filtered.get_conflicts(other_filtered));
}
}
}
conflicts
}
pub fn get_conflicts_single(&self, filtered_access: &FilteredAccess) -> AccessConflicts {
let mut conflicts = AccessConflicts::empty();
if !self.combined_access.is_compatible(filtered_access.access()) {
for filtered in &self.filtered_accesses {
conflicts.add(&filtered.get_conflicts(filtered_access));
}
}
conflicts
}
pub fn add(&mut self, filtered_access: FilteredAccess) {
self.combined_access.extend(&filtered_access.access);
self.filtered_accesses.push(filtered_access);
}
pub fn add_resource_read(&mut self, index: ComponentId) {
let mut filter = FilteredAccess::default();
filter.add_read(index);
filter.and_with(IS_RESOURCE);
self.add(filter);
}
pub fn add_unfiltered_component_read(&mut self, index: ComponentId) {
let mut filter = FilteredAccess::default();
filter.add_read(index);
self.add(filter);
}
pub fn add_unfiltered_read_all_components(&mut self) {
let mut filter = FilteredAccess::default();
filter.access.read_all();
self.add(filter);
}
pub fn add_resource_write(&mut self, index: ComponentId) {
let mut filter = FilteredAccess::default();
filter.add_write(index);
filter.and_with(IS_RESOURCE);
self.add(filter);
}
pub fn add_unfiltered_component_write(&mut self, index: ComponentId) {
let mut filter = FilteredAccess::default();
filter.add_write(index);
self.add(filter);
}
pub fn add_unfiltered_write_all_components(&mut self) {
let mut filter = FilteredAccess::default();
filter.write_all();
self.add(filter);
}
pub fn extend(&mut self, filtered_access_set: FilteredAccessSet) {
self.combined_access
.extend(&filtered_access_set.combined_access);
self.filtered_accesses
.extend(filtered_access_set.filtered_accesses);
}
pub fn read_all(&mut self) {
let mut filter = FilteredAccess::matches_everything();
filter.read_all();
self.add(filter);
}
pub fn write_all(&mut self) {
let mut filter = FilteredAccess::matches_everything();
filter.write_all();
self.add(filter);
}
pub fn clear(&mut self) {
self.combined_access.clear();
self.filtered_accesses.clear();
}
}
#[derive(Default, Eq)]
#[repr(transparent)]
pub struct ComponentIdSet(FixedBitSet);
impl PartialEq for ComponentIdSet {
fn eq(&self, other: &Self) -> bool {
self.0.symmetric_difference(&other.0).next().is_none()
}
}
impl ComponentIdSet {
#[inline]
pub const fn new() -> Self {
Self(FixedBitSet::new())
}
#[cfg(test)]
pub(crate) fn from_bits(bits: FixedBitSet) -> Self {
Self(bits)
}
#[inline]
pub fn insert(&mut self, index: ComponentId) {
self.0.grow_and_insert(index.index());
}
#[inline]
pub fn remove(&mut self, index: ComponentId) {
if index.index() < self.0.len() {
self.0.remove(index.index());
}
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
#[inline]
pub fn contains(&self, index: ComponentId) -> bool {
self.0.contains(index.index())
}
#[inline]
pub fn is_disjoint(&self, other: &ComponentIdSet) -> bool {
self.0.is_disjoint(&other.0)
}
#[inline]
pub fn is_subset(&self, other: &ComponentIdSet) -> bool {
self.0.is_subset(&other.0)
}
#[inline]
pub fn is_clear(&self) -> bool {
self.0.is_clear()
}
#[inline]
pub fn iter(&self) -> ComponentIdIter<Ones<'_>> {
ComponentIdIter(self.0.ones())
}
#[inline]
pub fn union<'a>(&'a self, other: &'a ComponentIdSet) -> ComponentIdIter<Union<'a>> {
ComponentIdIter(self.0.union(&other.0))
}
#[inline]
pub fn intersection<'a>(
&'a self,
other: &'a ComponentIdSet,
) -> ComponentIdIter<Intersection<'a>> {
ComponentIdIter(self.0.intersection(&other.0))
}
#[inline]
pub fn difference<'a>(&'a self, other: &'a ComponentIdSet) -> ComponentIdIter<Difference<'a>> {
ComponentIdIter(self.0.difference(&other.0))
}
#[inline]
pub fn union_with(&mut self, other: &ComponentIdSet) {
self.0.union_with(&other.0);
}
#[inline]
pub fn intersect_with(&mut self, other: &ComponentIdSet) {
self.0.intersect_with(&other.0);
}
#[inline]
pub fn difference_with(&mut self, other: &ComponentIdSet) {
self.0.difference_with(&other.0);
}
#[inline]
pub fn difference_from(&mut self, other: &ComponentIdSet) {
self.0.grow(other.0.len());
self.0.toggle_range(..);
self.0.intersect_with(&other.0);
}
}
impl Debug for ComponentIdSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.ones()).finish()
}
}
impl Clone for ComponentIdSet {
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0);
}
}
impl IntoIterator for ComponentIdSet {
type Item = ComponentId;
type IntoIter = ComponentIdIter<IntoOnes>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ComponentIdIter(self.0.into_ones())
}
}
impl<'a> IntoIterator for &'a ComponentIdSet {
type Item = ComponentId;
type IntoIter = ComponentIdIter<Ones<'a>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl FromIterator<ComponentId> for ComponentIdSet {
#[inline]
fn from_iter<T: IntoIterator<Item = ComponentId>>(iter: T) -> Self {
Self(FixedBitSet::from_iter(
iter.into_iter().map(ComponentId::index),
))
}
}
impl Extend<ComponentId> for ComponentIdSet {
#[inline]
fn extend<T: IntoIterator<Item = ComponentId>>(&mut self, iter: T) {
self.0.extend(iter.into_iter().map(ComponentId::index));
}
}
#[repr(transparent)]
pub struct ComponentIdIter<I>(I);
impl<I: Iterator<Item = usize>> Iterator for ComponentIdIter<I> {
type Item = ComponentId;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(ComponentId::new)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<I: DoubleEndedIterator<Item = usize>> DoubleEndedIterator for ComponentIdIter<I> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(ComponentId::new)
}
}
impl<I: FusedIterator<Item = usize>> FusedIterator for ComponentIdIter<I> {}
#[cfg(test)]
mod tests {
use crate::{
component::ComponentIds,
query::{
access::{AccessFilters, InvertibleComponentIdSet},
Access, AccessConflicts, ComponentAccessKind, ComponentIdSet, FilteredAccess,
FilteredAccessSet, UnboundedAccessError,
},
};
use alloc::{vec, vec::Vec};
use fixedbitset::FixedBitSet;
#[test]
fn test_access_clone() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_5 = ids.next_mut();
let mut original = Access::default();
original.add_read(id_1);
original.add_read(id_2);
original.add_write(id_3);
original.add_archetypal(id_5);
original.read_all();
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_access_clone_from() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let id_5 = ids.next_mut();
let id_7 = ids.next_mut();
let id_8 = ids.next_mut();
let mut original = Access::default();
original.add_read(id_1);
original.add_read(id_2);
original.add_write(id_3);
original.add_archetypal(id_5);
original.read_all();
let mut cloned = Access::default();
cloned.add_write(id_7);
cloned.add_read(id_4);
cloned.add_archetypal(id_8);
cloned.write_all();
cloned.clone_from(&original);
assert_eq!(original, cloned);
}
#[test]
fn test_filtered_access_clone() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let mut original = FilteredAccess::default();
original.add_write(id_1);
original.add_read(id_2);
original.add_required(id_3);
original.and_with(id_4);
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_filtered_access_clone_from() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let id_7 = ids.next_mut();
let mut original = FilteredAccess::default();
original.add_write(id_1);
original.add_read(id_2);
original.add_required(id_3);
original.and_with(id_4);
let mut cloned = FilteredAccess::default();
cloned.add_write(id_7);
cloned.add_read(id_4);
cloned.append_or(&FilteredAccess::default());
cloned.clone_from(&original);
assert_eq!(original, cloned);
}
#[test]
fn test_access_filters_clone() {
let mut ids = ComponentIds::default();
let id_3 = ids.next_mut();
let id_5 = ids.next_mut();
let mut original = AccessFilters::default();
original.with.insert(id_3);
original.without.insert(id_5);
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_access_filters_clone_from() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_5 = ids.next_mut();
let mut original = AccessFilters::default();
original.with.insert(id_3);
original.without.insert(id_5);
let mut cloned = AccessFilters::default();
cloned.with.insert(id_1);
cloned.without.insert(id_2);
cloned.clone_from(&original);
assert_eq!(original, cloned);
}
#[test]
fn test_filtered_access_set_clone() {
let mut ids = ComponentIds::default();
let id_2 = ids.next_mut();
let id_4 = ids.next_mut();
let mut original = FilteredAccessSet::default();
original.add_unfiltered_component_read(id_2);
original.add_unfiltered_component_write(id_4);
original.read_all();
let cloned = original.clone();
assert_eq!(original, cloned);
}
#[test]
fn test_filtered_access_set_from() {
let mut ids = ComponentIds::default();
let id_2 = ids.next_mut();
let id_4 = ids.next_mut();
let id_7 = ids.next_mut();
let id_9 = ids.next_mut();
let mut original = FilteredAccessSet::default();
original.add_unfiltered_component_read(id_2);
original.add_unfiltered_component_write(id_4);
original.read_all();
let mut cloned = FilteredAccessSet::default();
cloned.add_unfiltered_component_read(id_7);
cloned.add_unfiltered_component_write(id_9);
cloned.write_all();
cloned.clone_from(&original);
assert_eq!(original, cloned);
}
#[test]
fn read_all_access_conflicts() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let mut access_a = Access::default();
access_a.add_write(id_0);
let mut access_b = Access::default();
access_b.read_all();
assert!(!access_b.is_compatible(&access_a));
let mut access_a = Access::default();
access_a.read_all();
let mut access_b = Access::default();
access_b.read_all();
assert!(access_b.is_compatible(&access_a));
}
#[test]
fn access_get_conflicts() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let mut access_a = Access::default();
access_a.add_read(id_0);
access_a.add_read(id_1);
let mut access_b = Access::default();
access_b.add_read(id_0);
access_b.add_write(id_1);
assert_eq!(access_a.get_conflicts(&access_b), vec![id_1].into());
let mut access_c = Access::default();
access_c.add_write(id_0);
access_c.add_write(id_1);
assert_eq!(access_a.get_conflicts(&access_c), vec![id_0, id_1].into());
assert_eq!(access_b.get_conflicts(&access_c), vec![id_0, id_1].into());
let mut access_d = Access::default();
access_d.add_read(id_0);
assert_eq!(access_d.get_conflicts(&access_a), AccessConflicts::empty());
assert_eq!(access_d.get_conflicts(&access_b), AccessConflicts::empty());
assert_eq!(access_d.get_conflicts(&access_c), vec![id_0].into());
}
#[test]
fn filtered_combined_access() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let mut access_a = FilteredAccessSet::default();
access_a.add_unfiltered_component_read(id_1);
let mut filter_b = FilteredAccess::default();
filter_b.add_write(id_1);
let conflicts = access_a.get_conflicts_single(&filter_b);
assert_eq!(
&conflicts,
&AccessConflicts::from(vec![id_1]),
"access_a: {access_a:?}, filter_b: {filter_b:?}"
);
}
#[test]
fn filtered_access_extend() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let mut access_a = FilteredAccess::default();
access_a.add_read(id_0);
access_a.add_read(id_1);
access_a.and_with(id_2);
let mut access_b = FilteredAccess::default();
access_b.add_read(id_0);
access_b.add_write(id_3);
access_b.and_without(id_4);
access_a.extend(&access_b);
let mut expected = FilteredAccess::default();
expected.add_read(id_0);
expected.add_read(id_1);
expected.and_with(id_2);
expected.add_write(id_3);
expected.and_without(id_4);
assert!(access_a.eq(&expected));
}
#[test]
fn filtered_access_extend_or() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let mut access_a = FilteredAccess::default();
access_a.add_write(id_0);
access_a.add_write(id_1);
let mut access_b = FilteredAccess::default();
access_b.and_with(id_2);
let mut access_c = FilteredAccess::default();
access_c.and_with(id_3);
access_c.and_without(id_4);
access_b.append_or(&access_c);
access_a.extend(&access_b);
let mut expected = FilteredAccess::default();
expected.add_write(id_0);
expected.add_write(id_1);
expected.filter_sets = vec![
AccessFilters {
with: ComponentIdSet::from_bits(FixedBitSet::with_capacity_and_blocks(3, [0b111])),
without: ComponentIdSet::default(),
},
AccessFilters {
with: ComponentIdSet::from_bits(FixedBitSet::with_capacity_and_blocks(4, [0b1011])),
without: ComponentIdSet::from_bits(FixedBitSet::with_capacity_and_blocks(
5,
[0b10000],
)),
},
];
assert_eq!(access_a, expected);
}
#[test]
fn try_iter_component_access_simple() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_5 = ids.next_mut();
let mut access = Access::default();
access.add_read(id_1);
access.add_read(id_2);
access.add_write(id_3);
access.add_archetypal(id_5);
let result = access.try_iter_access().map(Iterator::collect::<Vec<_>>);
assert_eq!(
result,
Ok(vec![
ComponentAccessKind::Shared(id_1),
ComponentAccessKind::Shared(id_2),
ComponentAccessKind::Exclusive(id_3),
ComponentAccessKind::Archetypal(id_5),
]),
);
}
#[test]
fn try_iter_component_access_unbounded_write_all() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let mut access = Access::default();
access.add_read(id_1);
access.add_read(id_2);
access.write_all();
let result = access.try_iter_access().map(Iterator::collect::<Vec<_>>);
assert_eq!(
result,
Err(UnboundedAccessError {
writes_inverted: true,
reads_inverted: true
}),
);
}
#[test]
fn try_iter_component_access_unbounded_read_all() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let mut access = Access::default();
access.add_read(id_1);
access.add_read(id_2);
access.read_all();
let result = access.try_iter_access().map(Iterator::collect::<Vec<_>>);
assert_eq!(
result,
Err(UnboundedAccessError {
writes_inverted: false,
reads_inverted: true
}),
);
}
fn bit_set(bits: usize, iter: impl IntoIterator<Item = usize>) -> ComponentIdSet {
let mut result = FixedBitSet::with_capacity(bits);
result.extend(iter);
ComponentIdSet::from_bits(result)
}
#[test]
fn invertible_union_tests() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let set0 = ComponentIdSet::from_iter([id_0]);
let set1 = ComponentIdSet::from_iter([id_1]);
let set2 = ComponentIdSet::from_iter([id_2]);
let set01 = ComponentIdSet::from_iter([id_0, id_1]);
let set02 = ComponentIdSet::from_iter([id_0, id_2]);
let set012 = ComponentIdSet::from_iter([id_0, id_1, id_2]);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.union(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Included(set012.clone())
);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.union(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Excluded(set2.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.union(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Excluded(set1.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.union(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Excluded(set0.clone())
);
}
#[test]
fn invertible_union_with_different_lengths() {
let mut self_set = InvertibleComponentIdSet::Included(bit_set(1, [0]));
let other_set = InvertibleComponentIdSet::Excluded(bit_set(3, [0, 1]));
self_set.union_with(&other_set);
assert_eq!(
self_set,
InvertibleComponentIdSet::Excluded(bit_set(3, [1]))
);
}
#[test]
fn invertible_difference_tests() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let set0 = ComponentIdSet::from_iter([id_0]);
let set1 = ComponentIdSet::from_iter([id_1]);
let set2 = ComponentIdSet::from_iter([id_2]);
let set01 = ComponentIdSet::from_iter([id_0, id_1]);
let set02 = ComponentIdSet::from_iter([id_0, id_2]);
let set012 = ComponentIdSet::from_iter([id_0, id_1, id_2]);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.difference(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Included(set1.clone())
);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.difference(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Included(set0.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.difference(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Excluded(set012.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.difference(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Included(set2.clone())
);
}
#[test]
fn invertible_intersection_tests() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let set0 = ComponentIdSet::from_iter([id_0]);
let set1 = ComponentIdSet::from_iter([id_1]);
let set2 = ComponentIdSet::from_iter([id_2]);
let set01 = ComponentIdSet::from_iter([id_0, id_1]);
let set02 = ComponentIdSet::from_iter([id_0, id_2]);
let set012 = ComponentIdSet::from_iter([id_0, id_1, id_2]);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.intersection(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Included(set0.clone())
);
assert_eq!(
InvertibleComponentIdSet::Included(set01.clone())
.intersection(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Included(set1.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.intersection(&InvertibleComponentIdSet::Included(set02.clone())),
InvertibleComponentIdSet::Included(set2.clone())
);
assert_eq!(
InvertibleComponentIdSet::Excluded(set01.clone())
.intersection(&InvertibleComponentIdSet::Excluded(set02.clone())),
InvertibleComponentIdSet::Excluded(set012.clone())
);
}
#[test]
fn component_id_set_insert_remove_clear() {
let mut ids = ComponentIds::default();
let id_0 = ids.next_mut();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let mut set = ComponentIdSet::new();
assert!(!set.contains(id_0));
assert!(!set.contains(id_1));
assert!(!set.contains(id_2));
assert!(set.is_clear());
set.insert(id_2);
set.insert(id_1);
assert!(!set.contains(id_0));
assert!(set.contains(id_1));
assert!(set.contains(id_2));
assert!(!set.is_clear());
set.remove(id_1);
assert!(!set.contains(id_0));
assert!(!set.contains(id_1));
assert!(set.contains(id_2));
assert!(!set.is_clear());
set.insert(id_2);
set.insert(id_1);
assert!(!set.contains(id_0));
assert!(set.contains(id_1));
assert!(set.contains(id_2));
assert!(!set.is_clear());
set.clear();
assert!(!set.contains(id_0));
assert!(!set.contains(id_1));
assert!(!set.contains(id_2));
assert!(set.is_clear());
}
#[test]
fn component_id_set_remove_out_of_range() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let mut set = ComponentIdSet::new();
set.remove(id_3);
set.insert(id_1);
set.remove(id_4);
assert!(set.iter().eq([id_1]));
}
#[test]
fn component_id_set_is_subset_is_disjoint() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let id_4 = ids.next_mut();
let id_5 = ids.next_mut();
let set_1234 = ComponentIdSet::from_iter([id_1, id_2, id_3, id_4]);
let set_23 = ComponentIdSet::from_iter([id_2, id_3]);
let set_45 = ComponentIdSet::from_iter([id_4, id_5]);
assert!(set_23.is_subset(&set_1234));
assert!(!set_1234.is_subset(&set_23));
assert!(set_23.is_disjoint(&set_45));
assert!(set_45.is_disjoint(&set_23));
assert!(!set_1234.is_disjoint(&set_23));
assert!(!set_23.is_disjoint(&set_1234));
}
#[test]
fn component_id_set_union_intersection_difference() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let set_13 = ComponentIdSet::from_iter([id_1, id_3]);
let set_23 = ComponentIdSet::from_iter([id_2, id_3]);
assert!(set_13.union(&set_23).eq([id_1, id_3, id_2]));
assert!(set_23.union(&set_13).eq([id_2, id_3, id_1]));
assert!(set_13.intersection(&set_23).eq([id_3]));
assert!(set_23.intersection(&set_13).eq([id_3]));
assert!(set_13.difference(&set_23).eq([id_1]));
assert!(set_23.difference(&set_13).eq([id_2]));
}
#[test]
fn component_id_set_union_intersection_difference_with() {
let mut ids = ComponentIds::default();
let id_1 = ids.next_mut();
let id_2 = ids.next_mut();
let id_3 = ids.next_mut();
let set_13 = ComponentIdSet::from_iter([id_1, id_3]);
let set_23 = ComponentIdSet::from_iter([id_2, id_3]);
let mut s = set_13.clone();
s.union_with(&set_23);
assert!(s.iter().eq([id_1, id_2, id_3]));
let mut s = set_23.clone();
s.union_with(&set_13);
assert!(s.iter().eq([id_1, id_2, id_3]));
let mut s = set_13.clone();
s.intersect_with(&set_23);
assert!(s.iter().eq([id_3]));
let mut s = set_23.clone();
s.intersect_with(&set_13);
assert!(s.iter().eq([id_3]));
let mut s = set_13.clone();
s.difference_with(&set_23);
assert!(s.iter().eq([id_1]));
let mut s = set_23.clone();
s.difference_with(&set_13);
assert!(s.iter().eq([id_2]));
let mut s = set_13.clone();
s.difference_from(&set_23);
assert!(s.iter().eq([id_2]));
let mut s = set_23.clone();
s.difference_from(&set_13);
assert!(s.iter().eq([id_1]));
}
}