Skip to main content

mittens_engine/engine/ecs/
world_query_adapter.rs

1//! Bridge between `World` topology and the `mittens-query` evaluator.
2//!
3//! `WorldQueryAdapter` lets `QueryEvaluator` walk the live ECS using the same
4//! adapter trait that the module CE-tree query uses. Engine subsystems that
5//! need to look up components by name/type should go through this adapter
6//! rather than rolling their own walks.
7
8use crate::engine::ecs::{ComponentId, World};
9use mittens_query::{AttributeSelector, QueryTreeAdapter};
10
11pub struct WorldQueryAdapter<'w> {
12    world: &'w World,
13}
14
15impl<'w> WorldQueryAdapter<'w> {
16    pub fn new(world: &'w World) -> Self {
17        Self { world }
18    }
19}
20
21impl<'w> QueryTreeAdapter for WorldQueryAdapter<'w> {
22    type NodeId = ComponentId;
23
24    fn children_of(&self, node: Self::NodeId) -> Vec<Self::NodeId> {
25        self.world.children_of(node).to_vec()
26    }
27
28    fn matches_type(&self, node: Self::NodeId, type_name: &str) -> bool {
29        self.world
30            .component_name(node)
31            .map_or(false, |t| t.eq_ignore_ascii_case(type_name))
32    }
33
34    fn matches_name(&self, node: Self::NodeId, name: &str) -> bool {
35        self.world
36            .component_label(node)
37            .map_or(false, |n| n == name)
38    }
39
40    fn matches_guid(&self, node: Self::NodeId, guid: &str) -> bool {
41        let Ok(parsed) = uuid::Uuid::parse_str(guid) else {
42            return false;
43        };
44        self.world
45            .get_component_record(node)
46            .map_or(false, |n| n.guid == parsed)
47    }
48
49    fn matches_attribute(&self, node: Self::NodeId, attribute: &AttributeSelector) -> bool {
50        match attribute.name.as_str() {
51            "name" => attribute
52                .value
53                .as_deref()
54                .map(|name| self.matches_name(node, name))
55                .unwrap_or(false),
56            "guid" => attribute
57                .value
58                .as_deref()
59                .map(|guid| self.matches_guid(node, guid))
60                .unwrap_or(false),
61            _ => false,
62        }
63    }
64}