#traits #map #dynamic #downcast

trait-map-derive

为trait_map包生成TraitMapEntry特质的代码

3个版本

0.1.2 2023年2月17日
0.1.1 2023年2月17日
0.1.0 2023年2月17日

#28#downcast


用于 trait-map

GPL-3.0-or-later

19KB
149

特质映射

Rust动态特质存储和引用的映射

注意:此库必须在Rust Nightly上编译。它使用了ptr_metadataunsize特性。

关于

这个包允许你在映射中动态搜索特质。例如,假设我们有一些特质和实现了这些特质的结构体

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 */ }
}

我们可以使用TraitMap来对dyn Trait类型进行迭代,如下所示

use trait_map::{TraitMap, TraitMapEntry, Context};

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>) {
    // Must explicitly list which traits to expose
    context
      .downcast::<Self>()
      .add_trait::<dyn ExampleTrait>()
      .add_trait::<dyn ExampleTraitTwo>();
  }
}

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();
  }
}

派生

如果你启用了derive功能标志,你可以自动派生TraitMapEntry。你需要使用一个或多个#[trait_map(...)]宏来指定要注册到TraitMap的特质。它使用proc_macro_diagnostic特性在Nightly编译时发出有用的警告。

use trait_map::TraitMapEntry;

// ...

#[derive(Debug, TraitMapEntry)]
#[trait_map(ExampleTrait, ExampleTraitTwo)]
#[trait_map(std::fmt::Debug)]
struct DerivedStruct {
  // ...
}

impl ExampleTrait for DerivedStruct {
  fn do_something(&self) -> u32 { /* Code */ }
  fn do_another_thing(&mut self) { /* Code */ }
}

impl ExampleTraitTwo for DerivedStruct{
  fn test_method(&self) { /* Code */ }
}

依赖

~1.5MB
~36K SLoC