2 个版本

0.1.4 2020 年 3 月 1 日
0.1.3 2020 年 2 月 28 日
0.1.2 2020 年 2 月 27 日
0.1.1 2020 年 2 月 26 日
0.1.0 2020 年 2 月 25 日

#2029数据结构

MIT 许可证

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);

没有运行时依赖项