use alloc::vec::Vec;
use core::cmp;
use crate::{
archetype::{Archetype, ArchetypeId},
archetypes::Archetypes,
component::ComponentKey,
};
#[derive(Default, Debug, Clone)]
pub struct ArchetypeSearcher {
pub(crate) required: Vec<ComponentKey>,
}
impl ArchetypeSearcher {
pub fn add_required(&mut self, component: ComponentKey) {
self.required.push(component)
}
#[inline]
pub(crate) fn find_archetypes<'a>(
&mut self,
archetypes: &'a Archetypes,
mut result: impl FnMut(ArchetypeId, &'a Archetype),
) {
self.required.sort();
self.required.dedup();
traverse_archetypes(archetypes, archetypes.root(), &self.required, &mut result);
}
}
#[inline]
pub(crate) fn traverse_archetypes<'a>(
archetypes: &'a Archetypes,
cur: ArchetypeId,
required: &[ComponentKey],
result: &mut impl FnMut(ArchetypeId, &'a Archetype),
) {
let arch = archetypes.get(cur);
match required {
[] => {
result(cur, arch);
for &arch_id in arch.children.values() {
traverse_archetypes(archetypes, arch_id, required, result);
}
}
[head, tail @ ..] => {
for (&component, &arch_id) in &arch.children {
match component.cmp(head) {
cmp::Ordering::Less => {
traverse_archetypes(archetypes, arch_id, required, result);
}
cmp::Ordering::Equal => {
traverse_archetypes(archetypes, arch_id, tail, result);
}
cmp::Ordering::Greater => {
}
}
}
}
}
}