5个版本
0.2.2 | 2021年8月17日 |
---|---|
0.2.1 | 2020年10月28日 |
0.2.0 | 2020年4月24日 |
0.1.1 | 2020年4月17日 |
0.1.0 | 2020年3月22日 |
#17 in #casting
1,770 每月下载量
在 44 个crate中使用(通过 intertrait)
13KB
249 代码行
Intertrait
此库提供类型实现特质对象之间的直接转换。
在Rust中,如果类型已知,可以将在std::any::Any
子特质的特质对象在运行时向下转换到具体类型。但两个特质对象之间(即不涉及支撑值的具体类型)的直接转换是不可能的(甚至还没有从特质的特质对象到其超特质的转换)。
使用此crate,如果目标特质在使用此crate提供的宏预先注册,则可以任何在CastFrom
子特质的特质对象可以直接转换到由底层类型实现的另一个特质的特质对象。
依赖关系
将以下两个依赖项添加到您的Cargo.toml
[dependencies]
intertrait = "0.2"
linkme = "0.2"
linkme
依赖项由于在intertrait
宏的输出中使用linkme
宏而需要。
用法
use intertrait::*;
use intertrait::cast::*;
struct Data;
trait Source: CastFrom {}
trait Greet {
fn greet(&self);
}
#[cast_to]
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
impl Source for Data {}
fn main() {
let data = Data;
let source: &dyn Source = &data;
let greet = source.cast::<dyn Greet>();
greet.unwrap().greet();
}
目标特质必须提前明确指定。有三种方法可以做到这一点
#[cast_to]
到 impl
项
指定的特质的实现被指定为目标特质。
use intertrait::*;
struct Data;
trait Greet { fn greet(&self); }
#[cast_to]
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
#[cast_to(Trait)]
到类型定义
对于类型,指定为#[cast_to(...)]
属性参数的特征被指定为目标特征。
use intertrait::*;
trait Greet { fn greet(&self); }
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
#[cast_to(Greet, std::fmt::Debug)]
#[derive(std::fmt::Debug)]
struct Data;
castable_to!(类型=>特征1,特征2)
对于类型,:
之后的特征被指定为目标特征。
use intertrait::*;
#[derive(std::fmt::Debug)]
struct Data;
trait Greet { fn greet(&self); }
impl Greet for Data {
fn greet(&self) {
println!("Hello");
}
}
// Only in an item position due to the current limitation in the stable Rust.
// https://github.com/rust-lang/rust/pull/68717
castable_to!(Data => Greet, std::fmt::Debug);
fn main() {}
std::sync::Arc
支持
std::sync::Arc
的独特之处在于它只实现了downcast
方法,条件是对象类型为dyn Any + Send + Sync + 'static'.
使用Arc
时,应采取以下步骤
- 将源特征标记为
CastFromSync
而不是CastFrom
- 将
[sync]
标志添加到#[cast_to]
和castable_to!
,如下所示#[cast_to([sync])] #[cast_to([sync] Trait1, Trait2)] castable_to!(Type => [sync] Trait, Trait2);
工作原理
首先,CastFrom
特征使得从一个子特征的CastFrom
对象中检索到std::any::Any
对象成为可能。
intertrait
提供的宏生成用于将std::any::Any
特质的对象向下转换为具体类型,并从中创建目标特质的特质的跳转函数。
这些跳转函数使用linkme
crate聚合到一个全局注册表中,该注册表使用TypeId
对进行键控,这些是CastFrom
子特质的特质的对象支持的具体类型的以及目标特质的(实际实现略有不同,但概念上是这样的)。
在这个过程中,它不依赖于任何不稳定的Rust实现细节,例如可能在未来更改的特质对象的布局。
致谢
intertrait
从伟大的traitcast
crate中吸取了许多核心思想。
许可
根据以下任一许可获得许可
- Apache License,版本 2.0 (LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- 麻省理工学院许可证(《LICENSE-MIT》或http://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确表示 otherwise,否则您根据Apache-2.0许可证定义的任何有意提交以包含在作品中的贡献,应如上双许可,不附加任何额外条款或条件。
依赖关系
~2MB
~42K SLoC