//! Low-level querying. use std::iter::{repeat_n, FlatMap, RepeatN, Zip}; use crate::component::storage::archetype::{Archetype, EntityIter}; use crate::component::storage::{ArchetypeRefIter, ArchetypeSearchTerms}; use crate::entity::Handle as EntityHandle; use crate::query::Terms; use crate::World; /// Low-level entity query structure. #[derive(Debug)] pub struct Query<'world, const MAX_TERM_CNT: usize> { world: &'world World, terms: Terms, } impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT> { /// Iterates over the entities matching this query. #[must_use] pub fn iter(&self) -> Iter<'_, 'world> { Iter { iter: self .world .data .component_storage .search_archetypes(ArchetypeSearchTerms { present: &self.terms.present, absent: &self.terms.absent }) .flat_map( (|archetype| { repeat_n(archetype, archetype.entity_cnt()) .zip(archetype.entities()) }) as ComponentIterMapFn, ), world: self.world, } } #[must_use] pub fn world(&self) -> &'world World { self.world } pub(crate) fn new(world: &'world World, terms: Terms) -> Self { Self { world, terms } } } impl<'query, 'world, const MAX_TERM_CNT: usize> IntoIterator for &'query Query<'world, MAX_TERM_CNT> { type IntoIter = Iter<'query, 'world>; type Item = EntityHandle<'world>; fn into_iter(self) -> Self::IntoIter { self.iter() } } pub struct Iter<'query, 'world> { iter: QueryEntityIter<'query, 'world>, world: &'world World, } impl<'query, 'world> Iterator for Iter<'query, 'world> { type Item = EntityHandle<'world>; fn next(&mut self) -> Option { let (archetype, entity) = self.iter.next()?; Some(EntityHandle::new(archetype, entity, self.world)) } } type ComponentIterMapFnOutput<'a> = Zip, EntityIter<'a>>; type ComponentIterMapFn = for<'a> fn(&'a Archetype) -> ComponentIterMapFnOutput<'a>; type QueryEntityIter<'query, 'world> = FlatMap< ArchetypeRefIter<'world, 'query>, ComponentIterMapFnOutput<'world>, ComponentIterMapFn, >;