Return object in vector of trait objects if it matches a specified type

I'm working on an ECS system, and a vital piece of functionality that I'd like to implement is a way to get a component from an entity, based on the type of component desired.

In this project, an Entity is defined as a struct with a field named components. components is a vector of trait objects, the trait being Component which as of now is an empty trait.

I want a function which takes a type T, checks through the components of an entity, and if it finds a component of type T within, returns it (or the first instance of it attached to the Entity, wrapped in a Result).

Here's all that in code:

pub trait Component {}

pub struct Entity<'a> {
    pub components: Vec<&'a dyn Component>
}

impl<'a> Entity<'a> {
    pub fn get_component<T>(&self) -> Result<&mut T, ()>
        where T: Component
    {
        for c in &self.components {
            //--------------------------------------------------------
            // How do I check whether the type of component that c   |
            // refers to matches T, and if it does, return it?       |
            // Is that even the best way of doing this?              |
            //--------------------------------------------------------
        }

        return Err(());
    }
}

Probably the simplest way to do this is to require each Component type to be 'static, then use a HashMap to organize the components by their type_id(). Alternatively, require each Component type to declare some kind of uuid(), then use it to organize them in a HashMap, BTreeMap, etc.

For finding all entities of this kind, it's as simple as

impl<'a> Entity<'a> {
    pub fn get_component<T>(&self) -> impl Iterator<Item = &T> + '_
        where T: Any + Component
    {
        self.components.iter().filter_map(|c| c.as_any().downcast_ref())
    }
}

However, the HashMap/BTreeMap approach suggested above may be superior if there is a large number of components (since then iterating over the entire collection would scale linearly with the number of components).

1 Like