-1

I have this function that sends an HTTP request parses the response and returns a Result:

pub fn get_network_info(&self) -> Result<NetworkInfoResult, &'static str> {
    let rpc = JsonRpc::new(
        String::from("1.0"),
        self.settings.id.clone(),
        String::from("getnetworkinfo"),
        Vec::new(),
    );
    let url = format!("http://{}:{}", self.settings.url, self.settings.port);
    let req = HttpRequest::new_json_rpc(
        url,
        rpc,
        self.settings.user.clone(),
        self.settings.pass.clone(),
    );
    match req.execute() {
        Ok(x) => {
            println!("{}", x.content);
            let parsed: NetworkInfo = serde_json::from_str(&x.content)
                .expect("Failed to parse networkinfo Json response");
            if parsed.id != self.settings.id {
                Err("RPC Request and Response id didn't match!")
            } else {
                if parsed.error.is_some() {
                    Err(&parsed.error.unwrap())
                } else {
                    Ok(parsed.result)
                }
            }
        }
        Err(e) => Err(e),
    }
}

If the error field is set in the JSON response we want to return an error, in particular the error message inside the response. Otherwise, we return the result field of the parsed response.

The problem which this code is that Err(&parsed.error.unwrap()) doesn't compile. The reason for this is that the lifetime of the variable containing the parsed.error.unwrap() is only within the function, therefore it might not exist anymore in the context of the caller.

My problem is that Err expects a reference to a string, but whatever reference I try to pass would be to a local or temporary variable. How do I work around this issue?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Jakob Abfalter
  • 4,980
  • 17
  • 54
  • 94
  • 1
    That code is far from idiomatic. Please consider revisiting chapter 9 from the book, specifically on the subject of [propagating errors](https://doc.rust-lang.org/stable/book/ch09-02-recoverable-errors-with-result.html#propagating-errors). – E_net4 Nov 16 '20 at 13:42
  • It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Nov 16 '20 at 14:09
  • Since you didn't provide a [MRE], I can't modify your code to apply the duplicate, but the key is `pub fn get_network_info(&self) -> Result` – Shepmaster Nov 16 '20 at 14:09

1 Answers1

0

My problem is that Err expects a reference to a string, but whatever reference I try to pass would be to a local or temporary variable. Can anybody help me work around this issue?

The "workaround" is to fix the function's signature. Either return a full-blown String, or if you really need the efficiency return a Cow (so you can return either a String or an &'static str). Since parsed is a local you can't return a reference to it.

Masklinn
  • 34,759
  • 3
  • 38
  • 57