#weak #rc #traits #trait-object

dependent_view

从引用类型生成弱特质的包装器

3个稳定版本

使用旧版Rust 2015

1.0.2 2018年8月2日
1.0.1 2018年8月1日

1328Rust模式

每月下载 22

MIT 许可证

29KB
258

dependent_view 构建状态 构建状态

dependent_view 是一个Rust库,它提供围绕 RcArc 类型的简单包装器,使它们能够为系统的不同组件提供非所有者结构的“视图”。

使用方法

将此添加到您的 Cargo.toml

[dependencies]
dependent_view="1"

并将其添加到您的crate根目录

#[macro_use]
extern crate dependent_view;

该库提供了两个主要的结构体 DependentRcDependentArc,用于普通和线程安全的视图。

这些修改了视图类型的结果(在 std::rc::Weakstd::sync::Weak 之间)。

要从这些对象获取 Weak<Trait>,分别使用宏 to_view!()to_view_sync()

在编译时检查 DependentRc<T> 实现的类型 T 是否实现了您想要获取视图的特质(请参阅示例)。

与标准的 RcBox 相比,这些依赖类型提供了一种不同的所有权委托方式。

一个 DependentRc 应被视为其包含类型的单一所有者,然而与 Box 不同,它允许用户为对象生成多个运行时管理的 Weak<Trait> 引用(对于包含实体实现的每个 Trait) - 这些 Weak 引用一旦 DependantRc 被丢弃就不再可以升级。

示例

假设我们有以下特性

trait Dance {
    fn dance(&self);
}

trait Prance {
    fn prance(&self);
}

以及实现这些特性的某些结构体

struct Dancer {id: usize}
impl Dance for Dancer {fn dance(&self) {println!("D{:?}", self.id);}}
impl Prance for Dancer {fn prance(&self)  {println!("P{:?}", self.id);}}

struct Prancer {id: usize}
impl Dance for Prancer {fn dance(&self) {println!("D{:?}", self.id);}}
impl Prance for Prancer {fn prance(&self)  {println!("P{:?}", self.id);}}

我们可以使用新的函数创建 DependentRc

use dependent_view::rc::*;

let mut dancer = DependentRc::new(Dancer { id: 0 });
let mut prancer = DependentRc::new(Prancer { id: 0 });

我们可以使用这些 DependentRc 创建我们结构的非拥有视图

let dancer_dance_view : Weak<Dance> = to_view!(dancer);
let dancer_prance_view : Weak<Prance> = to_view!(dancer);

let prancer_dance_view : Weak<Dance> = to_view!(prancer);
let prancer_prance_view : Weak<Prance> = to_view!(prancer);

然后我们可以将这些视图共享给其他组件,而不用担心它们的删除问题

    let mut dancers : Vec<Weak<Dance>> = Vec::new();
    let mut prancers : Vec<Weak<Prance>> = Vec::new();

    {
        let mut dancer = DependentRc::new(Dancer { id: 0 });
        let mut prancer = DependentRc::new(Prancer { id: 0 });

        dancers.push(to_view!(dancer));
        prancers.push(to_view!(dancer));
        dancers.push(to_view!(prancer));
        prancers.push(to_view!(prancer));

        for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {
             dancer_ref.upgrade().unwrap().dance(); 
             prancer_ref.upgrade().unwrap().prance(); 
        }

       // at this point, dancer and prancer are dropped, invalidating the views
    }


    for (dancer_ref, prancer_ref) in dancers.iter().zip(prancers.iter()) {
       assert!(dancer_ref.upgrade().is_none());
       assert!(prancer_ref.upgrade().is_none());
    }

此外,当底层的结构体没有实现特性时,尝试生成结构体的特性视图将导致编译时错误

struct Bad { id: usize }
let bad = DependentRc::new(Bad { id: 0 });
let bad_view : Weak<Dance> = to_view!(bad); // compile time error

请参阅 example.rs 获取完整的源代码。

由于内部工作方式,如果编译器无法推断 to_view! 的结果类型,它会对在大小不同的类型上调用 std::mem::transmute 发出抱怨。这通常只在你实际上没有使用视图时发生 - 通常可以通过简单地添加类型注释来避免。

无运行时依赖