12个版本 (稳定)
使用旧的Rust 2015
1.2.1 | 2024年4月7日 |
---|---|
1.2.0 | 2020年6月30日 |
1.1.1 | 2019年10月28日 |
1.0.4 | 2019年4月9日 |
0.1.0 | 2015年12月16日 |
在Rust模式中排名16
每月下载量1,984,721
在3,611个crate中使用(直接使用221个)
34KB
450 行
downcast-rs
Rust的枚举非常适合在事先知道所有变体的情况下使用的类型。但用户定义类型的容器需要一种开闭类型,比如特质对象。某些应用程序可能希望将这些特质对象转换回原始的具体类型,以访问额外的功能和性能优化的内联实现。
downcast-rs
使用仅安全的Rust为特质对象添加了这种下转型支持。它支持类型参数、关联类型和约束。
使用方法
将以下内容添加到您的Cargo.toml
[dependencies]
downcast-rs = "1.2.1"
此crate与no_std
兼容。要在没有std
的情况下使用它
[dependencies]
downcast-rs = { version = "1.2.0", default-features = false }
要使一个特质可下转型,让它扩展downcast::Downcast
或downcast::DowncastSync
,并在它上调用impl_downcast!
,如下面的示例所示。
由于需要稳定访问alloc,从1.2.0版本开始,最低支持的Rust版本是1.36。
trait Trait: Downcast {}
impl_downcast!(Trait);
// Also supports downcasting `Arc`-ed trait objects by extending `DowncastSync`
// and starting `impl_downcast!` with `sync`.
trait TraitSync: DowncastSync {}
impl_downcast!(sync TraitSync);
// With type parameters.
trait TraitGeneric1<T>: Downcast {}
impl_downcast!(TraitGeneric1<T>);
// With associated types.
trait TraitGeneric2: Downcast { type G; type H; }
impl_downcast!(TraitGeneric2 assoc G, H);
// With constraints on types.
trait TraitGeneric3<T: Copy>: Downcast {
type H: Clone;
}
impl_downcast!(TraitGeneric3<T> assoc H where T: Copy, H: Clone);
// With concrete types.
trait TraitConcrete1<T: Copy>: Downcast {}
impl_downcast!(concrete TraitConcrete1<u32>);
trait TraitConcrete2<T: Copy>: Downcast { type H; }
impl_downcast!(concrete TraitConcrete2<u32> assoc H=f64);
无泛型示例
// Import macro via `macro_use` pre-1.30.
#[macro_use]
extern crate downcast_rs;
use downcast_rs::DowncastSync;
// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
// and run `impl_downcast!()` on the trait.
trait Base: DowncastSync {}
impl_downcast!(sync Base); // `sync` => also produce `Arc` downcasts.
// Concrete types implementing Base.
#[derive(Debug)]
struct Foo(u32);
impl Base for Foo {}
#[derive(Debug)]
struct Bar(f64);
impl Base for Bar {}
fn main() {
// Create a trait object.
let mut base: Box<Base> = Box::new(Foo(42));
// Try sequential downcasts.
if let Some(foo) = base.downcast_ref::<Foo>() {
assert_eq!(foo.0, 42);
} else if let Some(bar) = base.downcast_ref::<Bar>() {
assert_eq!(bar.0, 42.0);
}
assert!(base.is::<Foo>());
// Fail to convert `Box<Base>` into `Box<Bar>`.
let res = base.downcast::<Bar>();
assert!(res.is_err());
let base = res.unwrap_err();
// Convert `Box<Base>` into `Box<Foo>`.
assert_eq!(42, base.downcast::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
// Also works with `Rc`.
let mut rc: Rc<Base> = Rc::new(Foo(42));
assert_eq!(42, rc.downcast_rc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
// Since this trait is `Sync`, it also supports `Arc` downcasts.
let mut arc: Arc<Base> = Arc::new(Foo(42));
assert_eq!(42, arc.downcast_arc::<Foo>().map_err(|_| "Shouldn't happen.").unwrap().0);
}
具有关联类型和约束的泛型特质示例
// Can call macro via namespace since rust 1.30.
extern crate downcast_rs;
use downcast_rs::Downcast;
// To create a trait with downcasting methods, extend `Downcast` or `DowncastSync`
// and run `impl_downcast!()` on the trait.
trait Base<T: Clone>: Downcast { type H: Copy; }
downcast_rs::impl_downcast!(Base<T> assoc H where T: Clone, H: Copy);
// or: impl_downcast!(concrete Base<u32> assoc H=f32)
// Concrete types implementing Base.
struct Foo(u32);
impl Base<u32> for Foo { type H = f32; }
struct Bar(f64);
impl Base<u32> for Bar { type H = f32; }
fn main() {
// Create a trait object.
let mut base: Box<Base<u32, H=f32>> = Box::new(Bar(42.0));
// Try sequential downcasts.
if let Some(foo) = base.downcast_ref::<Foo>() {
assert_eq!(foo.0, 42);
} else if let Some(bar) = base.downcast_ref::<Bar>() {
assert_eq!(bar.0, 42.0);
}
assert!(base.is::<Bar>());
}
为什么有一段时间没有更新?
这个库是一个经过彻底测试的样板代码生成器,代码完整,没有不安全的代码,并且几乎不可能有任何安全漏洞需要修复。
许可证
版权所有2020,Ashish Myles(维护者)和贡献者。此软件在MIT和Apache 2.0许可证下双许可。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您提交给工作的任何有意贡献都应如上所述双许可,而不附加任何额外条款或条件。