Expand description
Trait Map
trait_map
provides the TraitMap data structure, which can store variable data types
and expose traits on those types. Types must implement the TraitMapEntry trait, which provides
on_create()
and on_update()
hooks
for specifying which traits should be exposed in the map.
Warning: This crate must be compiled using Rust Nightly.
It uses the ptr_metadata
and unsize
features for working with raw pointers.
Usage
Assume we have some custom structs and traits defined:
trait ExampleTrait {
fn do_something(&self) -> u32;
fn do_another_thing(&mut self);
}
trait ExampleTraitTwo {
fn test_method(&self);
}
struct MyStruct {
// ...
}
struct AnotherStruct {
// ...
}
impl ExampleTrait for MyStruct {
fn do_something(&self) -> u32 { /* Code */ }
fn do_another_thing(&mut self) { /* Code */ }
}
impl ExampleTrait for AnotherStruct {
fn do_something(&self) -> u32 { /* Code */ }
fn do_another_thing(&mut self) { /* Code */ }
}
impl ExampleTraitTwo for AnotherStruct{
fn test_method(&self) { /* Code */ }
}
We can specify that we want to allow our struct types to work with the trait map by implementing the TraitMapEntry trait:
impl TraitMapEntry for MyStruct {
fn on_create<'a>(&mut self, context: Context<'a>) {
// Must explicitly list which traits to expose
context
.downcast::<Self>()
.add_trait::<dyn ExampleTrait>();
}
// Can be overridden to update the exposed traits in the map
fn on_update<'a>(&mut self, context: Context<'a>) {
context
.downcast::<Self>()
.remove_trait::<dyn ExampleTrait>();
}
}
impl TraitMapEntry for AnotherStruct {
fn on_create<'a>(&mut self, context: Context<'a>) {
context
.downcast::<Self>()
.add_trait::<dyn ExampleTrait>()
.add_trait::<dyn ExampleTraitTwo>();
}
}
Once this is done, we can store instances of these concrete types inside TraitMap and query them by trait. For example:
fn main() {
let mut map = TraitMap::new();
map.add_entry(MyStruct { /* ... */ });
map.add_entry(AnotherStruct { /* ... */ });
// Can iterate over all types that implement ExampleTrait
// Notice that entry is "&dyn mut ExampleTrait"
for (entry_id, entry) in map.get_entries_mut::<dyn ExampleTrait>() {
entry.do_another_thing();
}
// Can iterate over all types that implement ExampleTraitTwo
// Notice that entry is "&dyn ExampleTraitTwo"
for (entry_id, entry) in map.get_entries::<dyn ExampleTraitTwo>() {
entry.test_method();
}
}
Structs
Opaque ID type for each entry in the trait map.
Map structure that allows types to be dynamically queries by trait.
Stores concrete type for an entry inside a TraitMap
Traits
Rust type that can be stored inside of a TraitMap.