You could probably engineer something using the Any trait, but I think I would prefer a hash map per resource. Alternatively an enum is probably better than a trait.
Thanks for pointing Any, it looks like the kind of RTTI I could use elsewhere. Reading Any code, I decided to run for the unsafe way. I could go back and use Any if RTTI is really a requirement.
In the purpose of knowledge, I share it here:
pub fn shader_code(&mut self, name: &str) -> &ShaderCodeResource {
let resource_id = calculate_hash(&name.to_string()) as ResourceId;
// Push new data if needed
if !self.registry.contains_key(&resource_id) {
// ...read the shader code...
let resource = Box::new(ShaderCodeResource { data: shader_code });
self.registry.insert(resource_id, resource);
}
// Try to return resource from registry.
match self.registry.get(&resource_id) {
Some(r) => {
return unsafe {
&*(r.as_ref() as *const dyn Resource as *const ShaderCodeResource)
}
}
None => panic!("Can't get resource after insert."),
}
}
So:
return unsafe {
&*(r.as_ref() as *const dyn Resource as *const ShaderCodeResource)
}
This part is actually taken from the Any source code, but without the Option deal, as we would actually use unwrap() for this.
Ouch. That smells like a really bad idea. You are basically using unsafe there in order to prevent type checking. Don't do that, it completely undermines the idea of strong, static typing.
Why are you trying to return a concrete type if your are storing trait objects? Or, conversely, why are you storing trait objects if you need a concrete type?
Unique identifiers are borderline useless without type information.
If you have a table of resources of N different types with unique IDs, but there's no way to take an ID and find the correct type, you effectively already have N different tables of different types; they're just interleaved for some reason. That is, you still have to know what type a thing is before you can use its ID to retrieve it from the table. The ID itself doesn't tell you anything. So you might as well actually make it N different tables with different types, and let the ID values overlap; the type information makes an ImageResourceId(42) distinct from a ShaderCodeResourceId(42) even though they both have the value 42. They're not interchangeable.
The only way to make them interchangeable is to put the type information inside the table -- either with some form of Any, or with an enum. Then you can have just a plain ResourceId(42) and look it up and decide what to do with the resource when you get it.