#downcast #traits #associated #any #no-std

no-std downcast-rs

仅使用安全的Rust支持特质对象下转型。它支持类型参数、关联类型和类型约束。

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

Download history 385254/week @ 2024-04-29 383834/week @ 2024-05-06 424681/week @ 2024-05-13 413519/week @ 2024-05-20 420810/week @ 2024-05-27 500962/week @ 2024-06-03 503730/week @ 2024-06-10 491470/week @ 2024-06-17 539855/week @ 2024-06-24 467890/week @ 2024-07-01 497383/week @ 2024-07-08 500752/week @ 2024-07-15 511852/week @ 2024-07-22 495945/week @ 2024-07-29 464938/week @ 2024-08-05 489269/week @ 2024-08-12

每月下载量1,984,721
3,611个crate中使用(直接使用221个)

MIT/Apache

34KB
450

downcast-rs

Build status Latest version Documentation

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::Downcastdowncast::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许可证定义,您提交给工作的任何有意贡献都应如上所述双许可,而不附加任何额外条款或条件。

无运行时依赖

特性