use crate::{
entity,
entity::allocator::Location,
query::{
filter::And,
view,
view::SubSet,
},
registry,
registry::contains::views::{
ContainsViewsOuter,
Sealed as ContainsViewsSealed,
},
Query,
World,
};
use core::marker::PhantomData;
pub struct Entry<'a, 'b, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
entries: &'b mut Entries<'a, Registry, Resources, Views, Indices>,
location: Location<Registry>,
}
impl<'a, 'b, Registry, Resources, Views, Indices> Entry<'a, 'b, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
fn new(
entries: &'b mut Entries<'a, Registry, Resources, Views, Indices>,
location: Location<Registry>,
) -> Self {
Self { entries, location }
}
}
impl<'a, 'b, Registry, Resources, Views, Indices> Entry<'a, 'b, Registry, Resources, Views, Indices>
where
Views: view::Views<'a>,
Registry: registry::ContainsViews<'a, Views, Indices>,
{
pub fn query<SubViews, Filter, FilterIndices, SubViewsFilterIndices, SubSetIndices>(
&mut self,
#[allow(unused_variables)] query: Query<SubViews, Filter>,
) -> Option<SubViews>
where
SubViews: SubSet<'a, Views, SubSetIndices> + view::Views<'a>,
Views: view::ContainsFilter<
'a,
And<Filter, SubViews>,
And<FilterIndices, SubViewsFilterIndices>,
>,
{
let indices = <<Registry as ContainsViewsSealed<'a, Views, Indices>>::Viewable as ContainsViewsOuter<'a, Views, <Registry as ContainsViewsSealed<'a, Views, Indices>>::Containments, <Registry as ContainsViewsSealed<'a, Views, Indices>>::Indices, <Registry as ContainsViewsSealed<'a, Views, Indices>>::ReshapeIndices>>::indices();
if unsafe { Views::filter(&indices, self.location.identifier) } {
let super_views = unsafe {
(*self.entries.world)
.archetypes
.get_mut(self.location.identifier)?
.view_row_maybe_uninit_unchecked::<Views, Indices>(self.location.index)
};
Some(unsafe { SubViews::view(super_views, indices, self.location.identifier) })
} else {
None
}
}
}
pub struct Entries<'a, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
world: *mut World<Registry, Resources>,
lifetime: PhantomData<&'a ()>,
views: PhantomData<Views>,
indices: PhantomData<Indices>,
}
impl<'a, Registry, Resources, Views, Indices> Entries<'a, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
pub(crate) unsafe fn new(world: *mut World<Registry, Resources>) -> Self {
Entries {
world,
lifetime: PhantomData,
views: PhantomData,
indices: PhantomData,
}
}
pub fn entry<'b>(
&'b mut self,
entity_identifier: entity::Identifier,
) -> Option<Entry<'a, 'b, Registry, Resources, Views, Indices>> {
unsafe { &*self.world }
.entity_allocator
.get(entity_identifier)
.map(|location| Entry::new(self, location))
}
}
unsafe impl<'a, Registry, Resources, Views, Indices> Send
for Entries<'a, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
}
unsafe impl<'a, Registry, Resources, Views, Indices> Sync
for Entries<'a, Registry, Resources, Views, Indices>
where
Registry: registry::Registry,
{
}
#[cfg(test)]
mod tests {
use super::Entries;
use crate::{
entity,
query::{
filter,
result,
Views,
},
Query,
Registry,
World,
};
use claims::{
assert_none,
assert_some,
};
#[derive(Debug, PartialEq)]
struct A(u32);
#[derive(Debug, PartialEq)]
struct B(char);
#[derive(Debug, PartialEq)]
struct C(f32);
type Registry = Registry!(A, B, C);
#[test]
fn empty_query() {
let mut world = World::<Registry!()>::new();
let identifier = world.insert(entity!());
let mut entries = unsafe { Entries::<_, _, Views!(), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!()>::new()));
}
#[test]
fn empty_query_with_filter_succeeds() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&A), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Has<A>>::new()));
}
#[test]
fn empty_query_with_filter_fails() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_none!(entry.query(Query::<Views!(), filter::Has<B>>::new()));
}
#[test]
fn empty_query_with_filter_on_mutable_ref_in_super_views() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&mut A), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Has<A>>::new()));
}
#[test]
fn empty_query_with_filter_on_optional_ref_in_super_views() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Has<A>>::new()));
}
#[test]
fn empty_query_with_filter_on_optional_mutable_ref_in_super_views() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&mut A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Has<A>>::new()));
}
#[test]
fn empty_query_with_filter_on_second_view_in_super_views() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&C, &A), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Has<A>>::new()));
}
#[test]
fn empty_query_with_or_filter() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(
entry.query(Query::<Views!(), filter::Or<filter::Has<A>, filter::Has<B>>>::new())
);
}
#[test]
fn empty_query_with_or_filter_second() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(
entry.query(Query::<Views!(), filter::Or<filter::Has<B>, filter::Has<A>>>::new())
);
}
#[test]
fn empty_query_with_and_filter() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a')));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(
entry.query(Query::<Views!(), filter::And<filter::Has<A>, filter::Has<B>>>::new())
);
}
#[test]
fn empty_query_with_not_filter() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(&B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!(), filter::Not<filter::Has<B>>>::new()));
}
#[test]
fn empty_query_with_nonempty_superset() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!());
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
assert_some!(entry.query(Query::<Views!()>::new()));
}
#[test]
fn query_immutable_superset_immutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(&A)>::new()));
assert_eq!(a, &A(42));
}
#[test]
fn query_immutable_superset_mutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(&C)>::new()));
assert_eq!(c, &C(3.14));
}
#[test]
fn query_mutable_superset_mutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(&mut C)>::new()));
assert_eq!(c, &mut C(3.14));
}
#[test]
fn query_optional_immutable_superset_immutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(Option<&A>)>::new()));
assert_eq!(a, Some(&A(42)));
}
#[test]
fn query_optional_immutable_superset_mutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(Option<&C>)>::new()));
assert_eq!(c, Some(&C(3.14)));
}
#[test]
fn query_optional_immutable_superset_mutable_not_present() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a')));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(Option<&C>)>::new()));
assert_eq!(c, None);
}
#[test]
fn query_optional_mutable_superset_mutable() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(Option<&mut C>)>::new()));
assert_eq!(c, Some(&mut C(3.14)));
}
#[test]
fn query_optional_mutable_superset_mutable_not_present() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a')));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(c) = assert_some!(entry.query(Query::<Views!(Option<&mut C>)>::new()));
assert_eq!(c, None);
}
#[test]
fn query_optional_none() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), C(3.14)));
let mut entries = unsafe { Entries::<_, _, Views!(&A, &mut C, &B), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(b) = assert_some!(entry.query(Query::<Views!(Option<&B>)>::new()));
assert_eq!(b, None);
}
#[test]
fn query_entity_identifier() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42), B('a'), C(3.14)));
let mut entries =
unsafe { Entries::<_, _, Views!(&A, &mut C, entity::Identifier), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(queried_identifier) =
assert_some!(entry.query(Query::<Views!(entity::Identifier)>::new()));
assert_eq!(queried_identifier, identifier);
}
#[test]
fn query_multiple() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(B('a'), C(3.14)));
let mut entries =
unsafe { Entries::<_, _, Views!(&A, &mut B, entity::Identifier), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(queried_identifier, b, a) =
assert_some!(entry.query(Query::<Views!(entity::Identifier, &B, Option<&A>)>::new()));
assert_eq!(queried_identifier, identifier);
assert_eq!(a, None);
assert_eq!(b, &B('a'));
}
#[test]
fn query_ref_with_optional_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(&A)>::new()));
assert_eq!(a, &A(42));
}
#[test]
fn query_ref_with_optional_mutable_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&mut A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(&A)>::new()));
assert_eq!(a, &A(42));
}
#[test]
fn query_mutable_ref_with_optional_mutable_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&mut A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(&mut A)>::new()));
assert_eq!(a, &mut A(42));
}
#[test]
fn query_optional_with_optional_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(Option<&A>)>::new()));
assert_eq!(a, Some(&A(42)));
}
#[test]
fn query_optional_with_optional_mutable_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&mut A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(Option<&A>)>::new()));
assert_eq!(a, Some(&A(42)));
}
#[test]
fn query_optional_mutable_with_optional_mutable_super_view() {
let mut world = World::<Registry>::new();
let identifier = world.insert(entity!(A(42)));
let mut entries = unsafe { Entries::<_, _, Views!(Option<&mut A>), _>::new(&mut world) };
let mut entry = assert_some!(entries.entry(identifier));
let result!(a) = assert_some!(entry.query(Query::<Views!(Option<&mut A>)>::new()));
assert_eq!(a, Some(&mut A(42)));
}
}