[英]argument validation in clap v4
我正在使用 crate clap
v4。当我尝试编写针对正则表达式验证 arguments 的内容时,我遇到了一些生命周期问题。
我的代码如下:
pub fn validator_regex(r: &'static str) -> ValueParser {
ValueParser::from(move |s: &str| -> std::result::Result<&str, Error> {
let reg = regex::Regex::new(r).unwrap();
match reg.is_match(s) {
true => Ok(s),
false => Err(Error::from(format!("not matches {}", r))),
}
})
}
pub fn validator_identifier() -> ValueParser {
validator_regex("^[-_0-9a-zA-Z]+$")
}
和编译错误:
error: lifetime may not live long enough
--> main\./src\cmd\cmd_util.rs:440:21
|
437 | ValueParser::from(move |s: &str| -> std::result::Result<&str, Error> {
| - - let's call the lifetime of this reference `'2`
| |
| let's call the lifetime of this reference `'1`
...
440 | true => Ok(s),
| ^^^^^ returning this value requires that `'1` must outlive `'2`
能帮我解决这两个问题吗:
lifetime may not live long enough
错误,因为返回的&str
与闭包参数一样长,并且可以正常编译pub fn validator_regex(r: &'static str) -> impl Fn(&str) -> Result<&str, String> {
move |s: &str| -> Result<&str, String> {
let reg = regex::Regex::new(r).unwrap();
match reg.is_match(s) {
true => Ok(s),
false => Err(format!("not match {}", r)),
}
}
}
让我们看一下您正在调用的From
impl:
impl<P> From<P> for ValueParser
where
P: TypedValueParser + Send + Sync + 'static,
好的,看看TypedValueParser
:
impl<F, T, E> TypedValueParser for F
where
F: Fn(&str) -> Result<T, E> + Clone + Send + Sync + 'static,
E: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
T: Send + Sync + Clone,
因此,签名不是Fn(&str) -> Result<&str, E>
,而是<T> Fn(&str) -> Result<T, E>
。 有什么不同吗? 我们不能把&str
放在T
的地方吗?
这是非常不同的。 让我们注释生命周期:
// Fn(&str) -> Result<&str, E>
for<'a> Fn(&'a str) -> Result<&'a str, E>
// <T> Fn(&str) -> Result<T, E>
<&'b str> for<'a> Fn(&'a str) -> Result<&'b str, E>
'b
从哪里来? 它不能是 HRTB,因为它是在impl
header ( T
) 而不是特征边界 ( Fn
) 中声明的。 因此,它必须是一个固定的生命周期。 看到不匹配了吗? 我称为'a
和'b
的生命周期是编译器分别称为'1
和'2
的生命周期。 如果'b
是固定的,则不能从动态 HRTB 'a
中导出。
解决方法很简单:只是不要返回&str
,而是返回String
:
pub fn validator_regex(r: &'static str) -> ValueParser {
ValueParser::from(move |s: &str| -> std::result::Result<String, Error> {
let reg = regex::Regex::new(r).unwrap();
match reg.is_match(s) {
true => Ok(s.to_owned()),
false => Err(Error::from(format!("not matches {}", r))),
}
})
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.