5 个版本
| 0.2.4 | 2022 年 11 月 10 日 |
|---|---|
| 0.2.3 | 2022 年 9 月 25 日 |
| 0.2.2 | 2022 年 9 月 23 日 |
| 0.2.1 | 2022 年 9 月 22 日 |
| 0.2.0 | 2022 年 8 月 28 日 |
在 Rust 模式 中排名 1212
每月下载量 21 次
40KB
412 行代码(不包括注释)
trait_cast_rs
要求
此 crate 需要夜间编译器。
此 crate 能做什么?
此 crate 为 Any 添加了 TraitcastableAny 替换 trait。它类似于 Any trait,用于向下转换为具体类型。此外,TraitcastableAny trait 允许您直接向下转换为其他 &dyn Trait。
要使此功能正常工作,您必须在 make_trait_castable(Trait1, Trait2, ...) 属性宏中指定所有要向下转换的目标 traits。此宏可以应用于结构体、枚举和联合体。它为您指定的结构体、枚举或联合体实现了 TraitcastableAny trait。
注意:无需修改目标 traits。这允许您向下转换为不受您控制的库中的 traits。
用法
-
将
trait_cast_rscrate 添加到您的Cargo.toml并切换到夜间编译器。 -
将
#[make_trait_castable(Trait1, Trait2, ...)]宏添加到您的结构体/枚举/联合体中。列出您最终想要向下转换的所有 traits。您必须实现所有列出的 traits。 -
在整个代码中使用
dyn TraitcastableAny的引用,而不是dyn Any。 -
享受向下转换为 trait 对象。
示例
use trait_cast_rs::{
make_trait_castable, TraitcastableAny, TraitcastableAnyInfra, TraitcastableAnyInfraExt,
};
#[make_trait_castable(Print)]
struct Source(i32);
trait Print {
fn print(&self);
}
impl Print for Source {
fn print(&self) {
println!("{}", self.0)
}
}
let source = Box::new(Source(5));
let castable: Box<dyn TraitcastableAny> = source;
let x: &dyn Print = castable.downcast_ref().unwrap();
x.print();
更多示例 🔥
查看 示例。
如果您想要做一些make_trait_castable属性宏无法处理的操作(例如实现泛型结构体 - 欢迎提交pull请求),请查看manual*.rs示例。
还有可用的声明宏 - 查看示例with_decl_macro*.rs。
功能
-
alloc- 为Box、Rc和Arc添加特殊实现。默认功能。 -
const_sort- 使make_trait_castable和make_trait_castable_decl宏在编译时对traitcast_targets进行排序。当执行向下转换时,将执行二分搜索。对于具有大量向下转换目标类型的类型,可能会非常快。此外,用户代码还需要以下功能标志:
#![feature(const_trait_impl, const_mut_refs)] -
min_specialization- 为'static类型实现TraitcastableAny。即使是您无法控制的类型。然而,这些TraitcastableAny的默认实现没有向下转换目标。此外,用户代码还需要以下功能标志:
#![feature(min_specialization)] -
downcast_unchecked- 向向下转换函数添加*_unchecked变体。
向上转换为真正的Any
使用trait_upcasting rust功能,您甚至可以将任何&dyn TraitcastableAny转换为&dyn Any。或者,您可以将Any特质作为特质转换目标。但是,无法将其转换回TraitcastableAny(欢迎提交pull请求)。
作者
raldone01和onestacked是此库的主要作者和维护者。
许可证
该项目可以在以下许可证下发布:
由您选择。
贡献
除非您明确声明,否则任何有意提交以包含在您的工作中的贡献,根据Apache-2.0许可证定义,均将按照上述方式双许可,不附加任何其他条款或条件。
它是如何工作的
我将简要介绍我们的内部操作:💦
编译时
-
为每个向下转换路径向具体类型添加一个
casting函数。此函数接收一个dyn TraitcastableAny,然后使用背景中的Any将其向下转换为具体类型。最后,它将具体类型转换为所需的特质对象并返回它。 -
添加一个返回常量切片的
traitcast_targets函数,其中包含(typeid,转换的casting函数指针)。
运行时
- 获取目标数组
- 查找目标
typeid - 将函数指针转换回原始类型
- 调用函数指针以获取所需的特质对象
- 返回它
- 💲 利润 💲
安全性 🏰
- 所有未检查的
downcast函数变体都使用unsafe- 如预期。 - 不安全使用的另一个用途是函数指针的转换。然而,当它们被调用时,它们会转换回原始类型。所以这应该是
105%保存的。只要TypeId不冲突。
替代方案 (以及为什么我们的 crate 是最好的)
本替代方案部分并不全面,如需更客观/详细的比较,请参阅 cast_trait_object 的替代方案部分。
- mopa:最后一次更新是在6年前。有一些未解决的 不安全性问题。还要求对特质的本身进行修改,而我们已经修改了结构体/枚举/联合体(见上面的注释)。
- mopa-maintained:可能已修复一些问题,但代码库仍然很旧,只是版本升级。
- traitcast:在 crates.io 上没有提供说明文档。使用全局注册表,并带有
lazy_static。公平地说,它允许您使用默认的Any,并且不需要 nightly。
待办事项:一旦我们的最后一次更新是在6年前,就删除此部分。
链接
依赖
~215–295KB