我是生锈新手。下面的 get_x509 函数会创建一个编译器警告“无法返回引用本地数据的值
pem.contents
”。我想我明白为什么 - 因为返回值引用 pem.contents ,它仅在该函数的范围内 - 但我无法弄清楚如何让它工作。
下面代码中的 x509 函数来自 x509_parser crate
use x509_parser::prelude::*;
fn main() {
let cert = "";
get_x509(cert);
}
fn get_x509(cert: &str) -> X509Certificate {
let res_pem = parse_x509_pem(cert.as_bytes());
let x509_cert = match res_pem {
Ok((_, pem)) => {
let res_cert = parse_x509_certificate(&pem.contents);
match res_cert {
Ok((_, certificate)) => certificate,
Err(_err) => {
panic!("Parse failed")
}
}
}
Err(_err) => {
panic!("Parse failed")
}
};
return x509_cert;
}
我尝试将 cert 变量设置为静态值。如果我在 main() 函数中内联上述代码,它就可以工作(但我必须匹配 &res_pem 而不是 res_pem)。
根据x509-parser-0.14.0/src/certificate.rs,
parse_x509_certificate
的参数和返回值都具有与其关联的生命周期'a
。解决该问题的一种方法是将 get_x509
分成两个函数,并且可以以某种方式避免在调用 parse_x509_certificate
的第二个函数中进行本地引用。
以下代码可以编译(但在运行时会出现恐慌,因为
cert
为空):
fn main() {
let cert = "";
let pem = get_x509_pem(cert);
get_x509(&pem); // Return value is unused.
}
use x509_parser::prelude::*;
fn get_x509_pem(cert: &str) -> Pem {
let (_, pem) = parse_x509_pem(cert.as_bytes()).expect("Parse failed");
pem
}
fn get_x509(pem: &Pem) -> X509Certificate {
let x509_cert = match parse_x509_certificate(&pem.contents) {
Ok((_, certificate)) => certificate,
Err(_err) => {
panic!("Parse failed")
}
};
x509_cert
}
正如您所说,这里的问题是您有一些仅存在于函数上下文中的东西,并且您想要返回对它(或它的某些部分)的引用。但是,当函数执行完成时,底层数据将被删除,因此您将返回一个悬空引用 - Rust 可以防止这种情况发生。
解决这个问题的方法是(西蒙史密斯的答案很好地说明了)返回您想要引用的数据,而不仅仅是返回引用。因此,在您的情况下,您希望返回整个
resp_pem
对象,然后进行进一步的数据提取。
阅读库的文档,您似乎处于一种不幸的情况,无法将
res_pem
从函数移到静态空间,因为 parse_x509_pem
返回拥有的数据,而 X509Certificate
包含引用。因此,返回的证书的生命周期必须比函数的生命周期长,但是您引用的对象 (res_pem
) 由该函数拥有,并在函数执行完成时被删除。
我也有几乎同样的问题。我试图在结构中解析 CertificateDer 并使 X509Certificate 成为结构的一部分。 它说它需要一些生命周期,但最后,我总是要么知道这个东西没有足够的生命周期,要么无法返回引用。虽然它确实具有克隆特征,但似乎数据并没有被复制保存在结构中。
pub struct X509Information<'a> {
pub x509: Option<X509Certificate<'a>>,
pub subject: String,
pub attributes: std::collections::HashMap<String, String>,
}
当下一步工作时,结果无法保存在结构中:
pub fn parse_der_to_x509<'a>(
certificate: &'a CertificateDer<'a>
) -> Result<X509Certificate<'a>, String> {
match parse_x509_certificate(certificate) {
Ok((_, x509)) => Ok(x509),
Err(error) => Err(format!("error parsing certificate: {}", error))
}
}
还有其他想法吗?