寿命结构方法

时间:2018-02-09 17:30:01

标签: struct rust lifetime

我想要一些数据对象来序列化自己并创建一个可以通过UDP发送的自身版本。问题是序列化(String)创建的serde_json::to_string仅在范围结束时生活(这对我有意义)所以字节版本(&[u8]来自as_bytes )不能将其引用到范围之外。我尝试过添加一些生命周期参数,但没有成功;我还没有真正了解生命周期参数。

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use std::str;

#[derive(Debug, Serialize, Deserialize)]
struct Test {
    text: String,
}

impl Test {
    pub fn new(input: &str) -> Self {
        Test {
            text: String::from(input),
        }
    }

    pub fn to_utf8(&self) -> &[u8] {
        // serde_json::to_string returns Result<String, ...>
        // String.as_bytes() returns &[u8]
        serde_json::to_string(&self).unwrap().as_bytes()
    }
}

fn main() {
    let a = Test::new("abc");
    println!("{:?}", a.to_utf8());
}

Playground

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:22:9
   |
22 |         serde_json::to_string(&self).unwrap().as_bytes()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not live long enough
23 |     }
   |     - temporary value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 19:5...
  --> src/main.rs:19:5
   |
19 | /     pub fn to_utf8(&self) -> &[u8] {
20 | |         // serde_json::to_string returns Result<String, ...>
21 | |         // String.as_bytes() returns &[u8]
22 | |         serde_json::to_string(&self).unwrap().as_bytes()
23 | |     }
   | |_____^

1 个答案:

答案 0 :(得分:1)

正如您所做的那样,切片不会超出范围。我不认为你可以通过终身注释解决这个问题:明确的生命周期实际上可以使对象生存更长时间,它们只会阻止编译器对生命周期相同的过于严格的假设。

这样做的方法是将这些字节的所有权返回给调用者,而不是在片中借用它们。显而易见的候选人是Vec

pub fn to_utf8(&self) -> Vec<u8> {
    Vec::from(serde_json::to_string(&self).unwrap().as_bytes())
}

这是一个额外的副本,这是不幸的,但幸运的是,Serde提供了一个直接为您提供此输出的功能!

pub fn to_utf8(&self) -> Vec<u8> {
    serde_json::to_vec(&self).unwrap()
} 

现在您可以返回一个Vec<u8>,它将由呼叫者拥有,并且只要呼叫者需要,就会持续。您可以使用Vec<u8>与使用切片完全相同的方式,如果需要,您甚至可以从中借用底层切片。