Rust 在函数中返回serde_json创建的结构

Rust 在函数中返回serde_json创建的结构,rust,borrow-checker,Rust,Borrow Checker,我被困在一个看似简单的问题上。我明白为什么我看到了错误,但似乎无法解决它。很明显,我遗漏了一些基本的东西 fn terraform_deploy_info<'a>(app: &'a MyApp) -> std::result::Result<&MyAppDeployInfo, Error> { let terraform = process::Command::new("terraform") // We are quer

我被困在一个看似简单的问题上。我明白为什么我看到了错误,但似乎无法解决它。很明显,我遗漏了一些基本的东西

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),
    }
}
这对我来说很有意义,因为我在函数中创建结构并返回一个借用的引用,当函数完成时,引用当然会消失

但是,当我将返回类型更改为
std::result::result
(即,不返回引用)时,我似乎无法使
Ok(x)
正常工作…我得到一个错误:

expected struct `MyAppDeployInfo`, found reference
同样,这也是有意义的,因为
serde_json
创建了一个结构,然后我迭代引用,所以当我索引到集合中时,我正在查看引用

因此,我尝试了各种方法来获取结构值,如取消引用、
Box::new
clone()
to_owned()
,等等,但仍然无法使其工作


我已经搜索了这里的所有问题,阅读了这本书,等等,但我仍然不清楚如何解决这个问题…任何建议都将不胜感激。

在不了解您的项目更多信息的情况下(请下次制作),我想说您可以将
.iter()
调用改为
。改为\u iter()
。与其收集到
Vec
中,然后使用
get
,我只需直接使用迭代器:

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"),
}

观察代码段的类型

let m = data.deploy_info.value // value is a Vec<MyAppDeployInfo>
    .iter() // returns a Iterator<Item=&MyAppDeployInfo>
    .filter(|&x| x.app == "myapp")
    .collect::<Vec<_>>(); // collects into a Vec<&MyAppDeployInfo>

if m.len() > 1 {
    return Err(Error::MultipleDeployInfo);
}

match m.get(0) { // get() returns a reference to an element
                 // i.e. a &&MyAppDeployInfo
        Some(&x) // pattern match says x : &MyAppDeployInfo
            => Ok(x), // which matches the return type
                      // but you get a borrowing error.
        None => Err(Error::NoDeployInfo),
    }
}

太棒了,谢谢<我缺少的是编码>进入iter()和不使用
collect()
。现在可以了。太好了,谢谢你的详细解释!我现在完全明白了。
fn terraform_deploy_info(app: &MyApp) // no explicit lifetime needed
        -> std::result::Result<MyAppDeployInfo, Error> {
    let data = // ...

    let mut 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"),
    }
}