use crate::{
archetypes,
hlist::Reshape,
query::{
filter::And,
result::Results,
view,
},
registry,
registry::{
contains::filter::Sealed as ContainsFilterSealed,
ContainsQuery,
},
};
use core::{
iter::FusedIterator,
marker::PhantomData,
};
pub struct Iter<'a, Registry, Filter, Views, Indices>
where
Registry: registry::Registry,
Views: view::Views<'a>,
{
archetypes_iter: archetypes::IterMut<'a, Registry>,
current_results_iter: Option<<Views::Results as Results>::Iterator>,
filter: PhantomData<Filter>,
indices: PhantomData<Indices>,
}
impl<'a, Registry, Filter, Views, Indices> Iter<'a, Registry, Filter, Views, Indices>
where
Registry: registry::Registry,
Views: view::Views<'a>,
{
pub(crate) fn new(archetypes_iter: archetypes::IterMut<'a, Registry>) -> Self {
Self {
archetypes_iter,
current_results_iter: None,
filter: PhantomData,
indices: PhantomData,
}
}
}
impl<'a, Registry, Filter, Views, Indices> Iterator for Iter<'a, Registry, Filter, Views, Indices>
where
Views: view::Views<'a>,
Registry: ContainsQuery<'a, Filter, Views, Indices>,
{
type Item = Views;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(ref mut results) = self.current_results_iter {
if let result @ Some(_) = results.next() {
return result;
}
}
let archetype = self.archetypes_iter.find(|archetype| {
unsafe {
<Registry as ContainsFilterSealed<
And<Views, Filter>,
And<Registry::ViewsFilterIndices, Registry::FilterIndices>,
>>::filter(archetype.identifier())
}
})?;
self.current_results_iter = Some(
unsafe {
archetype.view::<Views, (
Registry::ViewsContainments,
Registry::ViewsIndices,
Registry::ViewsCanonicalContainments,
)>()
}
.reshape()
.into_iterator(),
);
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.current_results_iter.as_ref().map_or(
(0, Some(0)),
<Views::Results as Results>::Iterator::size_hint,
);
match (self.archetypes_iter.size_hint(), high) {
((0, Some(0)), Some(_)) => (low, high),
_ => (low, None),
}
}
#[inline]
fn fold<A, Fold>(self, mut init: A, mut fold: Fold) -> A
where
Fold: FnMut(A, Self::Item) -> A,
{
if let Some(results) = self.current_results_iter {
init = results.fold(init, &mut fold);
}
self.archetypes_iter.fold(init, |acc, archetype| {
if unsafe {
<Registry as ContainsFilterSealed<
And<Views, Filter>,
And<Registry::ViewsFilterIndices, Registry::FilterIndices>,
>>::filter(archetype.identifier())
} {
unsafe {
archetype.view::<Views, (
Registry::ViewsContainments,
Registry::ViewsIndices,
Registry::ViewsCanonicalContainments,
)>()
}
.reshape()
.into_iterator()
.fold(acc, &mut fold)
} else {
acc
}
})
}
}
impl<'a, Registry, Filter, Views, Indices> FusedIterator
for Iter<'a, Registry, Filter, Views, Indices>
where
Views: view::Views<'a>,
Registry: ContainsQuery<'a, Filter, Views, Indices>,
{
}
unsafe impl<'a, Registry, Filter, Views, Indices> Send
for Iter<'a, Registry, Filter, Views, Indices>
where
Registry: registry::Registry,
Views: view::Views<'a>,
{
}