在 Rust 中,如何将具有生命周期的对象推送到向量中?
In Rust, how to push an object with a lifetime into a vector?
我有一些类似于下面的代码,它尝试从 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 字符串的引用,所以没有办法安全地这样做?
仔细看serde_json::from_str
:
pub fn from_str<'a, T>(s: &'a str) -> Result<T>
where
T: Deserialize<'a>,
这表示反序列化的 T
与输入 s
共享相同的生命周期。此 允许 进行零拷贝反序列化,这就是您在 MyType
中得到的结果,其中 id
是对字符串切片的引用。这将 MyType
的生命周期绑定到 &resp_raw
的生命周期,后者是 fn example()
的本地生命周期。这行不通。
问题不能通过给buff
你给它的生命周期参数来解决。 example
函数拥有 MyType
指向的缓冲区。允许 MyType
到 "escape" 进入 Vec
将允许创建悬空引用,因为缓冲区一旦被销毁 example
returns.
改MyType
满足DeserializeOwned
,即不带生命周期参数。您需要一个 String
或一个(为了节省一点内存)一个 Box<str>
而不是 &str
.
我有一些类似于下面的代码,它尝试从 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 字符串的引用,所以没有办法安全地这样做?
仔细看serde_json::from_str
:
pub fn from_str<'a, T>(s: &'a str) -> Result<T>
where
T: Deserialize<'a>,
这表示反序列化的 T
与输入 s
共享相同的生命周期。此 允许 进行零拷贝反序列化,这就是您在 MyType
中得到的结果,其中 id
是对字符串切片的引用。这将 MyType
的生命周期绑定到 &resp_raw
的生命周期,后者是 fn example()
的本地生命周期。这行不通。
问题不能通过给buff
你给它的生命周期参数来解决。 example
函数拥有 MyType
指向的缓冲区。允许 MyType
到 "escape" 进入 Vec
将允许创建悬空引用,因为缓冲区一旦被销毁 example
returns.
改MyType
满足DeserializeOwned
,即不带生命周期参数。您需要一个 String
或一个(为了节省一点内存)一个 Box<str>
而不是 &str
.