Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
419 views
in Technique[技术] by (71.8m points)

rust - 在Rust中,如何将具有生命周期的对象推入向量?(In Rust, how to push an object with a lifetime into a vector?)

I've got code somewhat like the following, which attempts to read from a websocket, parse the JSON result into a struct, and push that struct onto a Vec buffer.

(我有类似以下代码的代码,该代码尝试从websocket读取,将JSON结果解析为结构,然后将该结构推入Vec缓冲区。)

The code however fails to compile, because the struct has a lifetime, and the borrow checker complains that the JSON string does not live long enough.

(但是,代码无法编译,因为该结构具有生存期,并且借用检查器抱怨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
                }
            }
        }
    }
}

The exact error is that borrowed value [&resp_raw] does not live long enough .

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

I'm wondering how I should restructure this code to satisfy the borrow checker;

(我想知道如何重组此代码以满足借阅检查器;)

what is the correct way to push a struct with a lifetime onto the Vec param?

(将具有生命周期的结构推入Vec参数的正确方法是什么?)

Or is it the case that the &'a str parsed into MyType actually still retains a reference to the original JSON string, so there's no way to safely do this?

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

  ask by LogicChains translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Look at serde_json::from_str carefully:

(仔细查看serde_json::from_str :)

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

This says that the T which is deserialized shares the same lifetime as the input s .

(这表示反序列化的T与输入s具有相同的生存期。)

This allows for zero-copy deserialization, which is what you get in MyType , where id is a reference to a string slice.

(这允许零拷贝反序列化,这是您在MyType获得的,其中id是对字符串切片的引用。)

This binds the lifetime of MyType to the lifetime of &resp_raw , which is local to fn example() .

(这&resp_raw MyType的生存期绑定到&resp_raw的生存期,这对于fn example()是本地的。)

This will not work.

(这是行不通的。)

The problem can't be solved by giving buff the lifetime-parameter you've given it.

(通过给buff赋予其寿命参数无法解决该问题。)

The example -function owns the buffer that MyType point into.

(example -函数拥有MyType指向的缓冲区。)

Allowing MyType to "escape" into the Vec would allow a dangling reference to be created, as the buffer is destroyed once example returns.

(允许MyType “转义”到Vec中将允许创建悬空引用,因为一旦example返回,缓冲区将被破坏。)

Change MyType to satisify DeserializeOwned , that is, take no lifetime parameter.

(更改MyType来满足DeserializeOwned ,即不采用生存期参数。)

You'll need a String or a (to safe a little memory) a Box<str> instead of a &str .

(您需要一个String或一个(为了保护一点内存) Box<str>而不是&str 。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...