3个稳定版本
使用旧版Rust 2015
1.0.2 | 2018年8月2日 |
---|---|
1.0.1 | 2018年8月1日 |
1328 在 Rust模式
每月下载 22 次
29KB
258 行
dependent_view
dependent_view 是一个Rust库,它提供围绕 Rc
和 Arc
类型的简单包装器,使它们能够为系统的不同组件提供非所有者结构的“视图”。
使用方法
将此添加到您的 Cargo.toml
[dependencies]
dependent_view="1"
并将其添加到您的crate根目录
#[macro_use]
extern crate dependent_view;
该库提供了两个主要的结构体 DependentRc
和 DependentArc
,用于普通和线程安全的视图。
这些修改了视图类型的结果(在 std::rc::Weak
或 std::sync::Weak
之间)。
要从这些对象获取 Weak<Trait>
,分别使用宏 to_view!()
或 to_view_sync()
。
在编译时检查 DependentRc<T>
实现的类型 T
是否实现了您想要获取视图的特质(请参阅示例)。
与标准的 Rc
或 Box
相比,这些依赖类型提供了一种不同的所有权委托方式。
一个 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
发出抱怨。这通常只在你实际上没有使用视图时发生 - 通常可以通过简单地添加类型注释来避免。