#traits #pointers #dynamic #specialization #reflection #send-sync

nightly no-std hv-alchemy

重型炼金术 - 变化之黑魔法,包装后供您安全使用和享受

1个不稳定版本

0.1.0 2021年11月12日

#1355 in 数据结构

MIT/Apache

105KB
2K SLoC

重型炼金术 - 变化之黑魔法,包装后供您安全使用和享受。

hv-alchemy 是一组特性和类型,它维护了一个全局运行时注册表(目前静态不可用,但 linkme crate 可能会在某个时刻发挥作用),其中包含特例对象虚函数表和其他类型信息,如大小、对齐、析构函数等。它需要Rust nightly版以使用 ptr_metadataunsizearbitrary_self_types 功能。

此crate允许您做一些事情

  • 在运行时询问:“我们知道此类型是否实现了此对象安全特例吗?”
  • dyn AlchemicalAny 下的类型下推到具体的类型 T
  • Dyndyn AlchemicalAny 下推到无大小的特例对象类型 dyn Trait
  • 复制和克隆类型,而无需编译时 CopyClone 约束(需要运行时注册的 CopyClone 实现)
  • 提取 SendSyncCopyClone 约束,这些约束可以在编译时使用,并在运行时根据类型实现的特性有条件地访问,以根据特性特别化行为
  • 在任何时间通过任何类型扩展 TypeTable(虚函数表注册表)以任何它已知静态实现的特性
  • 通过将 Type<T> 转换为 Box<dyn AlchemicalAny> 或任何其他为它实现的特性,在运行时访问“类型”
  • Default::default 函数指针项作为 fn() -> T 访问,其中 T 是实现 Default 的类型(在运行时检查,没有编译时 Default 绑定)
  • 给定一个 *const dyn AlchemicalAny,尝试使用 dyn AlchemicalAny 提供的类型表中的 Layout 来克隆它到一个新的分配

请勿滥用。 hv-alchemyno_std 兼容,但需要 alloc

注意事项

我们目前无法在编译时注册某些类型通过 Alchemy 实现的所有不同事物。因此,你基本上必须在你自己的 API 中提供某种类型的钩子(如果你依赖 Alchemy),这鼓励/提供了一种方法来将相关的特质对象添加到你所感兴趣的 TypeTable 中。例如 linkme 或目前损坏的 inventory crate 能够执行类似操作,但它们 不能在类型上普遍量化,因为这需要将一个 forall T. 绑定单形化为多个 Type::<T>::of().add::<...>() 调用,而 Rust 目前没有这样做的方法。

工作原理

Alchemy 保持一个全局静态的 HashMap,将 TypeId 映射到通过 Box::leak(在某个时刻这可能被切换到全局 Bump 区域或类似的东西)创建的 &'static TypeTable,这些 TypeTable 再次包含 HashMap,将 TypeId 映射到 &'static DynVtable;一个 DynVtable 代表某个特质对象 dyn SomeTrait 对于某个类型 SomeType 的 vtable。具体来说,如果你想检查某个对象是否实现了 fmt::Debug,Alchemy 的查找过程如下

  • 获取对象的 TypeTable。如果我们试图动态转换一个特质对象 dyn AlchemicalAny,只需调用其 .type_table() 方法即可。否则,如果知道 T 的静态类型(并且不需要静态 fmt::Debug 绑定),可以使用 Type::<T>::of()
    • 如果我们使用 Type::<T>::of(),Alchemy 会获取 TypeIdT 并用它在全球注册表中查找其对应的 TypeTable。如果没有找到,它会创建一个空的。
  • 获取 TypeIddyn fmt::Debug,然后使用它来查找 TypeTablevtables 映射中的相应 DynVtable
  • 如果我们在那里找到一个 DynVtable,根据不变性,我们知道其实现类型将是我们要检查的对象的类型,而其特质对象类型将是 dyn fmt::Debug。然后我们可以假设在原始引用/值上使用 DynVtable::to_dyn_object_pointer 是安全的,将其转换为 &dyn fmt::Debug。或者,如果我们只想知道它是否实现了 Debug,我们就有答案了。

许可证

根据您的选择,许可协议为以下之一

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交的任何有意包含在工作中的贡献,将按上述方式双许可,不附加任何额外条款或条件。

依赖项

~1.5MB
~19K SLoC