将牛场结构转换为拥有结构的便捷方法

问题描述 投票:0回答:2

我有一个定义如下的结构

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
rust
2个回答
10
投票

积木:

  • 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>


0
投票
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
© www.soinside.com 2019 - 2024. All rights reserved.