rust clap v4中的参数验证

xytpbqjk  于 2023-01-09  发布在  其他
关注(0)|答案(1)|浏览(186)

我正在使用crate clap v4。当我试图编写一些验证正则表达式参数的东西时,我遇到了一些生存期问题。

我的代码如下:

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`

在这两个问题上,有谁能帮我吗?

  • 如何在clap v4中验证正则表达式
  • 为什么这段代码中有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)),
        }
    }
}
jpfvwuh4

jpfvwuh41#

让我们看看您正在调用的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头文件中声明(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))),
        }
    })
}

相关问题