2 个版本
0.1.4 | 2020 年 3 月 1 日 |
---|---|
0.1.3 | 2020 年 2 月 28 日 |
0.1.2 |
|
0.1.1 |
|
0.1.0 |
|
#2029 在 数据结构
19KB
172 行
GSRS 或泛型自引用结构体
允许创建几乎任意的自引用结构体
有关详细信息,请参阅 docs.rs 上的文档
许可证
MIT
lib.rs
:
GSRS 或泛型自引用结构体
这个包帮助创建自定义可移动的自引用结构体。没有魔法。它只是将所有者和对其的引用包装在一个包中,并使用简单的但不安全的生命周期技巧。
自引用结构体通常被认为是在 Rust 中的反模式,因此如果您能够轻松地不使用它,那么您应该这样做。但有时您确实需要有一个自引用结构体。因此,以下是一些您确实需要 SRS
的例子
- 如果您有一个基于引用的结构(例如 Arena 图或任何在字符串之上使用切片构建的结构),并且您希望能够将其移动到另一个线程,或者将其放入 Vec。
- 如果您的 API 能够返回自包含值会更好。
不支持依赖生命周期(目前?这是否真正需要/可能?)
应该从 1.31(2018 版本)开始在任何稳定的 Rust 上工作
用法
简单示例
use gsrs::*;
struct Test{field:usize}
#[derive(Default)]
struct TestRef<'a>(Option<&'a Test>);
deref_with_lifetime!(TestRef);
// create owned part
let mut srs = SRS::<Test, TestRef>::new( Test{ field: 5 } );
// create self-referencing part
srs.with(|user, owner|*user = TestRef(Some(owner)));
// get self referencing part back
let r = srs.get_ref(|user, _| user.0.unwrap());
println!("{}", r.field);
或者您可以一次性完成创建。尽管如此,您仍然必须指定引用部分的类型,因为类型推理会因为生命周期变化而困惑。这可以解决,但只有当 GATs 稳定下来才能解决。
use gsrs::*;
struct Test{field:usize}
struct TestRef<'a>(&'a Test);
deref_with_lifetime!(TestRef);
// create owned part and self-referencing part
let mut srs = SRS::<_, TestRef>::create_with(
Test{ field: 5 },
|owner|TestRef(owner)
);
// get self referencing part back
let r = srs.get_ref(|user, _| user.0);
println!("{}", r.field);
引用部分可以是任意复杂的
use gsrs::*;
struct TestRef<'a>(Vec<&'a str>);
deref_with_lifetime!(TestRef);
// create owned part and self-referencing part
let mut srs = SRS::<_, TestRef>::create_with(
"long unicode string".to_owned(),
|owner|TestRef(owner.split(' ').collect())
);
// get self referencing part back
let r = srs.get_ref(|user, _| user.0[1]);
assert_eq!("unicode", r);
并且这不会编译,因为 get_ref
能够提供具有正确生命周期的返回值
srs.with(|user, owner|*user = TestRef(Some(owner)));
let r = srs.get_ref(|user, _| user.0.unwrap());
drop(srs);
println!("{}",r.field);
这也会失败,因为只能返回静态类型或静态类型的引用。这样做是为了防止更改具有内部可变性的某些内部引用。
let mut srs = SRS::<Test,TestRef<'static>>::create_with(
Test{field:5},
|owner|TestRef(owner),
);
// here closure returns TestRef<'a> not a reference
let r = srs.with(|user,_|user);
let mut ow = Box::new(Test{field:0});
let r = srs.split(&mut ow);
println!("{}",r.0.field);