0

我的代码有点像下面,它尝试从 websocket 中读取数据,将 JSON 结果解析为结构,然后将该结构推送到Vec缓冲区中。然而,代码无法编译,因为结构有生命周期,并且借用检查器抱怨 JSON 字符串的生命周期不够长。

use serde::{Deserialize, Serialize};
use tungstenite::client::AutoStream;
use tungstenite::protocol::WebSocket;

#[derive(Serialize, Deserialize, Debug, Clone)]
struct MyType<'a> {
    id: &'a str,
    count: i64,
}

fn example<'a>(
    conn: &mut WebSocket<AutoStream>,
    buff: &'a mut Vec<MyType<'a>>,
) -> Option<Box<dyn std::error::Error>> {
    match conn.read_message() {
        Err(err) => Some(err.into()),
        Ok(msg) => {
            let resp_raw = msg.to_string();
            let resp_parsed: Result<MyType<'a>, _> = serde_json::from_str(&resp_raw);
            match resp_parsed {
                Err(err) => Some(err.into()),
                Ok(resp) => {
                    buff.push(resp.clone());
                    None
                }
            }
        }
    }
}

确切的错误是borrowed value [&resp_raw] does not live long enough.

我想知道我应该如何重构这段代码以满足借用检查器;将具有生命周期的结构推送到Vec参数上的正确方法是什么?

还是&'a str解析成MyType实际上仍然保留对原始 JSON 字符串的引用,所以没有办法安全地做到这一点?

4

1 回答 1

1

serde_json::from_str仔细看:

pub fn from_str<'a, T>(s: &'a str) -> Result<T> 
where
    T: Deserialize<'a>, 

这表示Twhich 被反序列化与 input 共享相同的生命周期s。这允许零拷贝反序列化,这就是你得到的MyType,其中id是对字符串切片的引用。这将 的生命周期绑定MyType到 的生命周期&resp_raw,后者是 的本地生命周期fn example()。这行不通。

这个问题不能通过给出buff你给它的生命周期参数来解决。example-function 拥有MyType指向的缓冲区。允许MyType“逃逸”到Vec将允许创建悬空引用,因为缓冲区在example返回后被销毁。

MyType改为 satisify ,DeserializeOwned即不带生命周期参数。您将需要 aString或 a (以保护一点记忆) aBox<str>而不是 a &str

于 2019-12-01T12:44:09.873 回答