Использование serde_json :: from_str для десериализации в структуру со статической строкой & 'имеет ошибку времени жизни - PullRequest
1 голос
/ 05 июня 2019

Я пытаюсь протестировать мост JSON, который я настроил для использования со средами Dart, JS и Python UI.Это хорошо работает для тех, но когда я попытался использовать тот же интерфейс UI / логики в программе Rust, используя tui-rs, я получаю пожизненную ошибку при попытке десериализации результата логического потока в потоке пользовательского интерфейса.

IЯ понимаю, что использование JSON для связи между слоями, написанными на Rust, не идеальный способ сделать что-то, но, учитывая мои цели, я надеюсь, что это понятно.

Я пробовал клонирование, которое работало для сериализации вещейи отправлен из пользовательского интерфейса в логику, но это не сработало для десериализации из логики в пользовательский интерфейс

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

1 Ответ

1 голос
/ 06 июня 2019
struct BridgeResult {
    result: &'static str,
    data: Vec<String>,
}

BridgeResult определено для хранения result, который является статической строкой.Это несовместимо с чем-то, что будет десериализовано из входной строки.Вам либо нужен результат, чтобы быть владельцем String, либо что-то, что заимствовано из ввода.

Попробуйте

struct BridgeResult<'a> {
    result: &'a str,
    data: Vec<String>,
}
...