1个不稳定版本
0.1.0 | 2021年11月12日 |
---|
#1355 in 数据结构
105KB
2K SLoC
重型炼金术 - 变化之黑魔法,包装后供您安全使用和享受。
hv-alchemy
是一组特性和类型,它维护了一个全局运行时注册表(目前静态不可用,但 linkme
crate 可能会在某个时刻发挥作用),其中包含特例对象虚函数表和其他类型信息,如大小、对齐、析构函数等。它需要Rust nightly版以使用 ptr_metadata
、unsize
和 arbitrary_self_types
功能。
此crate允许您做一些事情
- 在运行时询问:“我们知道此类型是否实现了此对象安全特例吗?”
- 将
dyn AlchemicalAny
下的类型下推到具体的类型T
- Dyn将
dyn AlchemicalAny
下推到无大小的特例对象类型dyn Trait
- 复制和克隆类型,而无需编译时
Copy
和Clone
约束(需要运行时注册的Copy
和Clone
实现) - 提取
Send
、Sync
、Copy
和Clone
约束,这些约束可以在编译时使用,并在运行时根据类型实现的特性有条件地访问,以根据特性特别化行为 - 在任何时间通过任何类型扩展
TypeTable
(虚函数表注册表)以任何它已知静态实现的特性 - 通过将
Type<T>
转换为Box<dyn AlchemicalAny>
或任何其他为它实现的特性,在运行时访问“类型” - 将
Default::default
函数指针项作为fn() -> T
访问,其中 T 是实现Default
的类型(在运行时检查,没有编译时Default
绑定) - 给定一个
*const dyn AlchemicalAny
,尝试使用dyn AlchemicalAny
提供的类型表中的Layout
来克隆它到一个新的分配
请勿滥用。 hv-alchemy
与 no_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 会获取TypeId
的T
并用它在全球注册表中查找其对应的TypeTable
。如果没有找到,它会创建一个空的。
- 如果我们使用
- 获取
TypeId
的dyn fmt::Debug
,然后使用它来查找TypeTable
的vtables
映射中的相应DynVtable
。 - 如果我们在那里找到一个
DynVtable
,根据不变性,我们知道其实现类型将是我们要检查的对象的类型,而其特质对象类型将是dyn fmt::Debug
。然后我们可以假设在原始引用/值上使用DynVtable::to_dyn_object_pointer
是安全的,将其转换为&dyn fmt::Debug
。或者,如果我们只想知道它是否实现了Debug
,我们就有答案了。
许可证
根据您的选择,许可协议为以下之一
- Apache License, Version 2.0 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您提交的任何有意包含在工作中的贡献,将按上述方式双许可,不附加任何额外条款或条件。
依赖项
~1.5MB
~19K SLoC