I'm stuck on what seems like a simple issue. I get why I am seeing the error but can't seem to resolve it. Obviously I am missing something fundamental.
fn terraform_deploy_info<'a>(app: &'a MyApp) -> std::result::Result<&MyAppDeployInfo, Error> {
let terraform = process::Command::new("terraform")
// We are querying output values.
.arg("output")
// We want it in json format for easy processing.
.arg("-json")
.output()
.expect("failed to execute terraform");
let output = String::from_utf8_lossy(&terraform.stdout);
let data: TerraformOutputs = serde_json::from_str(&output).unwrap();
let m = data.deploy_info.value.iter().filter(|&x| x.app == "myapp").collect::<Vec<_>>();
if m.len() > 1 {
return Err(Error::MultipleDeployInfo);
}
match m.get(0) {
Some(&x) => Ok(x),
None => Err(Error::NoDeployInfo),
}
}
The error I get is:
borrowed value must be valid for the lifetime 'a as defined on the body at
Which makes sense to me, as I am creating the struct in the function and returning a borrowed reference, which of course goes away when the function is finished.
But, when I change the return type be std::result::Result<MyAppDeployInfo, Error>
(that is, not returning a reference) I can't seem to get Ok(x)
to work...I get an error:
expected struct `MyAppDeployInfo`, found reference
Again, this makes sense as serde_json
creates a structure and then I iterate through references, so when I index into the collection I am looking at a reference.
So I tried all sorts of things to get the struct value like dereferencing, Box::new
, clone()
, to_owned()
, etc and still can't get it to work.
I've searched all the issues here, read the book, etc and it is still not clear to me how I can resolve this...any pointers would be appreciated.
Without knowing more about your project (please produce an MCVE next time), I'd say that you can change the .iter()
call into .into_iter()
. Instead of collecting into a Vec
and then using get
, I'd simply work with the iterator directly:
let m = data.deploy_info.value.into_iter().filter(|&x| x.app == "myapp").fuse();
match (m.next(), m.next()) {
(None, None) => Err(Error::NoDeployInfo),
(Some(x), None) => Ok(x),
(Some(_), Some(_)) => Err(Error::MultipleDeployInfo),
(None, Some(_)) => panic!("Iterator::fuse broken"),
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With