我有一个定义如下的结构
struct Foo<'a> {
field1: &'a str,
field2: &'a str,
field3: &'a u8,
// ...
}
我用于从
mmap
ped 文件返回解析结果。对于一些成功的解析,我想存储结果以供以后处理,并且由于各种原因,处理将在内存释放后进行。我可以做类似的事情
struct OwnedFoo {
field1: String,
field2: String,
field3: Vec<u8>,
// ...
}
并手动将我感兴趣的所有
Foo
转换为 OwnedFoos
。不过我想知道我是否可以做类似的事情:
struct Foo<'a> {
field1: Cow<'a, str>,
field2: Cow<'a, str>,
field3: Cow<'a, u8>,
...
}
相反,是否有任何方法可以自动使所有
Cow
拥有并删除生命周期参数。我在库文档中没有找到任何似乎适用的内容。
类似:
let a = Foo { ... };
let a_owned = a.into_owned();
// do stuff with a_owned that I can't do with a
积木:
Cow::into_owned
将返回拥有的版本。'static
是程序的生命周期因此我们可以写一个实用函数:
use std::borrow::Cow;
fn into_owned<'a, B>(c: Cow<'a, B>) -> Cow<'static, B>
where B: 'a + ToOwned + ?Sized
{
Cow::Owned(c.into_owned())
}
您可以通过简单地将转换应用于所有字段来将其扩展为
Foo<'a>
成为 Foo<'static>
。
use std::borrow::Cow;
#[derive(Debug)]
struct Foo<'a> {
field1: &'a str,
field2: &'a str,
field3: &'a [u8],
// ...
}
#[derive(Debug)]
struct OwnedFoo {
field1: String,
field2: String,
field3: Vec<u8>,
// ...
}
#[derive(Debug)]
struct CowFoo<'a> {
field1: Cow<'a, str>,
field2: Cow<'a, str>,
// field3: Cow<'a, [u8]>,
// ...
}
struct CowFoo02<'a, X>
where
[X]: ToOwned<Owned = Vec<X>>,
{
values: Cow<'a, [X]>,
}
impl<'a, X: Clone + 'a> CowFoo02<'a, X>
where
[X]: ToOwned<Owned = Vec<X>>,
{
fn new(v: Cow<'a, [X]>) -> Self {
CowFoo02 { values: v }
}
}
fn main() {
let a = Foo {
field1: "test_str",
field2: "test_str2",
field3: "test_str3".as_bytes(),
};
let a_owned = OwnedFoo {
field1: "test_String".to_string(),
field2: "test_String".to_string(),
field3: "Vec_u8".into(),
};
let a_cow_owned = CowFoo {
field1: "test_cow1".into(),
field2: "test_cow2".into(),
// field3: "test_cow03".into(),
// "test_cow3".into(),
};
dbg!(a);
dbg!(a_owned);
dbg!(a_cow_owned);
println!("~~~~~~~~~~~");
println!();
// Creates a container from borrowed values of a slice
let readonly = [1, 2];
let borrowed = CowFoo02::new((&readonly[..]).into());
match borrowed {
CowFoo02 {
values: Cow::Borrowed(b),
} => println!("borrowed {b:?}"),
_ => panic!("expect borrowed value"),
}
let mut clone_on_write = borrowed;
// Mutates the data from slice into owned vec and pushes a new value on top
clone_on_write.values.to_mut().push(3);
println!("clone_on_write = {:?}", clone_on_write.values);
// The data was mutated. Let's check it out.
match clone_on_write {
CowFoo02 {
values: Cow::Owned(_),
} => println!("clone_on_write contains owned data"),
_ => panic!("expect owned data"),
}
}
[src/main.rs:59:5] a = Foo {
field1: "test_str",
field2: "test_str2",
field3: [
116,
101,
115,
116,
95,
115,
116,
114,
51,
],
}
[src/main.rs:60:5] a_owned = OwnedFoo {
field1: "test_String",
field2: "test_String",
field3: [
86,
101,
99,
95,
117,
56,
],
}
[src/main.rs:61:5] a_cow_owned = CowFoo {
field1: "test_cow1",
field2: "test_cow2",
}
~~~~~~~~~~~
borrowed [1, 2]
clone_on_write = [1, 2, 3]
clone_on_write contains owned data