使用 serde_json::from_str 反序列化为带有 &'static 字符串的结构存在生命周期错误
Using serde_json::from_str to deserialize into a struct with a &'static string has a lifetime error
我正在尝试测试我为 Dart、JS 和 Python UI 框架设置的 JSON 桥。它对那些工作正常,但是当我尝试使用 tui-rs 在 Rust 程序中进行相同的 UI/logic 拆分时,在 UI 线程上尝试反序列化逻辑线程结果时出现生命周期错误。
我知道使用 JSON 进行两层之间的通信都用 Rust 编写并不是理想的做事方式,但考虑到我的目标,我希望它是可以理解的。
我已经尝试过克隆,它适用于将事物序列化并从 UI 发送到逻辑,但这不适用于从逻辑反序列化到 UI
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use serde::{Deserialize, Serialize};
#[macro_export]
macro_rules! BridgeResult {
($result:expr, $data:expr) => {
BridgeResult {
result: $result,
data: vec![$data.to_string()],
}
};
}
#[derive(Serialize, Deserialize)]
struct BridgeResult {
result: &'static str,
data: Vec<String>,
}
#[derive(Serialize, Deserialize)]
struct App {
state: i64,
}
impl Default for App {
fn default() -> App {
App { state: 0 }
}
}
fn main() {
let (to_logic, from_ui) = mpsc::channel();
let (to_ui, from_logic) = mpsc::channel();
ui(to_logic, from_logic);
logic(to_ui, from_ui);
}
fn ui(tx: Sender<(String, String)>, rx: Receiver<(String)>) {
let app = App::default();
let app_string = serde_json::to_string(&app)
.expect("failed to encode app struct for sending to logic heard");
tx.send(("binary_switch".to_string(), app_string))
.expect("failed to send binary_switch call and data to logic thread");
let output_string = rx
.recv()
.expect("failed to get a result from logic's initialize");
let output: BridgeResult = serde_json::from_str(&output_string)
.expect("failed to decode result from logic's binary_switch");
if output.result != "Ok()" {
panic!("init failed due to: \n {:?}", output.data);
} else {
println!("{:?}", output.data);
}
}
fn logic(tx: Sender<(String)>, rx: Receiver<(String, String)>) {
loop {
let (function, arguments) = rx
.recv()
.expect("failed to receive function and arguments from ui thread");
let result = match function.as_str() {
"binary_switch" => binary_switch(&arguments),
_ => {
BridgeResult! {"Err()", format!("cannot find rust function branch matching {}", function)}
}
};
let output = match serde_json::to_string(&result) {
Ok(output) => output,
Err(_) => "{'result' : 'Err()', 'data': 'failed exit encoding!!!'}".to_string(),
};
tx.send(output)
.expect("failed to send the output back to the ui thread");
}
}
fn binary_switch(data: &String) -> BridgeResult {
#[derive(Deserialize)]
struct Arguments {
state: i64,
}
let mut arguments: Arguments = match serde_json::from_str(&data) {
Ok(data) => data,
Err(err) => return BridgeResult! {"Err()", format!("failed to parse arguments\n, {}", err)},
};
if arguments.state == 0 {
arguments.state += 1;
} else {
arguments.state -= 1;
}
BridgeResult! {"Ok()", arguments.state}
}
我希望这会反序列化 BridgeResult
类型并使用其中应包含字符串 1 的数据字段。实际上我得到:
error[E0597]: `output_string` does not live long enough
--> src/main.rs:55:53
|
55 | let output: BridgeResult = serde_json::from_str(&output_string)
| ---------------------^^^^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `output_string` is borrowed for `'static`
...
63 | }
| - `output_string` dropped here while still borrowed
struct BridgeResult {
result: &'static str,
data: Vec<String>,
}
BridgeResult
被定义为保存一个 result
,它是一个静态字符串。这与将从输入字符串反序列化的内容不兼容。您要么需要结果是自己拥有的 String
,要么是从输入中借来的。
尝试
struct BridgeResult<'a> {
result: &'a str,
data: Vec<String>,
}
我正在尝试测试我为 Dart、JS 和 Python UI 框架设置的 JSON 桥。它对那些工作正常,但是当我尝试使用 tui-rs 在 Rust 程序中进行相同的 UI/logic 拆分时,在 UI 线程上尝试反序列化逻辑线程结果时出现生命周期错误。
我知道使用 JSON 进行两层之间的通信都用 Rust 编写并不是理想的做事方式,但考虑到我的目标,我希望它是可以理解的。
我已经尝试过克隆,它适用于将事物序列化并从 UI 发送到逻辑,但这不适用于从逻辑反序列化到 UI
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
use serde::{Deserialize, Serialize};
#[macro_export]
macro_rules! BridgeResult {
($result:expr, $data:expr) => {
BridgeResult {
result: $result,
data: vec![$data.to_string()],
}
};
}
#[derive(Serialize, Deserialize)]
struct BridgeResult {
result: &'static str,
data: Vec<String>,
}
#[derive(Serialize, Deserialize)]
struct App {
state: i64,
}
impl Default for App {
fn default() -> App {
App { state: 0 }
}
}
fn main() {
let (to_logic, from_ui) = mpsc::channel();
let (to_ui, from_logic) = mpsc::channel();
ui(to_logic, from_logic);
logic(to_ui, from_ui);
}
fn ui(tx: Sender<(String, String)>, rx: Receiver<(String)>) {
let app = App::default();
let app_string = serde_json::to_string(&app)
.expect("failed to encode app struct for sending to logic heard");
tx.send(("binary_switch".to_string(), app_string))
.expect("failed to send binary_switch call and data to logic thread");
let output_string = rx
.recv()
.expect("failed to get a result from logic's initialize");
let output: BridgeResult = serde_json::from_str(&output_string)
.expect("failed to decode result from logic's binary_switch");
if output.result != "Ok()" {
panic!("init failed due to: \n {:?}", output.data);
} else {
println!("{:?}", output.data);
}
}
fn logic(tx: Sender<(String)>, rx: Receiver<(String, String)>) {
loop {
let (function, arguments) = rx
.recv()
.expect("failed to receive function and arguments from ui thread");
let result = match function.as_str() {
"binary_switch" => binary_switch(&arguments),
_ => {
BridgeResult! {"Err()", format!("cannot find rust function branch matching {}", function)}
}
};
let output = match serde_json::to_string(&result) {
Ok(output) => output,
Err(_) => "{'result' : 'Err()', 'data': 'failed exit encoding!!!'}".to_string(),
};
tx.send(output)
.expect("failed to send the output back to the ui thread");
}
}
fn binary_switch(data: &String) -> BridgeResult {
#[derive(Deserialize)]
struct Arguments {
state: i64,
}
let mut arguments: Arguments = match serde_json::from_str(&data) {
Ok(data) => data,
Err(err) => return BridgeResult! {"Err()", format!("failed to parse arguments\n, {}", err)},
};
if arguments.state == 0 {
arguments.state += 1;
} else {
arguments.state -= 1;
}
BridgeResult! {"Ok()", arguments.state}
}
我希望这会反序列化 BridgeResult
类型并使用其中应包含字符串 1 的数据字段。实际上我得到:
error[E0597]: `output_string` does not live long enough
--> src/main.rs:55:53
|
55 | let output: BridgeResult = serde_json::from_str(&output_string)
| ---------------------^^^^^^^^^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `output_string` is borrowed for `'static`
...
63 | }
| - `output_string` dropped here while still borrowed
struct BridgeResult {
result: &'static str,
data: Vec<String>,
}
BridgeResult
被定义为保存一个 result
,它是一个静态字符串。这与将从输入字符串反序列化的内容不兼容。您要么需要结果是自己拥有的 String
,要么是从输入中借来的。
尝试
struct BridgeResult<'a> {
result: &'a str,
data: Vec<String>,
}