繁体   English   中英

clap v4 中的参数验证

[英]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`

能帮我解决这两个问题吗:

  • 如何在 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)),
        }
    }
}

让我们看一下您正在调用的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM