迭代Rust中的命名正则表达式组

时间:2016-08-27 18:34:48

标签: rust

我希望将匹配中的所有命名组提取到HashMap中,并且在尝试编译此代码时遇到“运行时间不够长”的错误:

extern crate regex;

use std::collections::HashMap;
use regex::Regex;

pub struct Route {
    regex: Regex,
}

pub struct Router<'a> {
    pub namespace_seperator: &'a str,
    routes: Vec<Route>,
}

impl<'a> Router<'a> {
    // ...

    pub fn path_to_params(&self, path: &'a str) -> Option<HashMap<&str, &str>> {
        for route in &self.routes {
            if route.regex.is_match(path) {
                let mut hash = HashMap::new();
                for cap in route.regex.captures_iter(path) {
                    for (name, value) in cap.iter_named() {
                        hash.insert(name, value.unwrap());
                    }
                }
                return Some(hash);
            }
        }
        None
    }
}

fn main() {}

这是错误输出:

error: `cap` does not live long enough
  --> src/main.rs:23:42
   |>
23 |>                     for (name, value) in cap.iter_named() {
   |>                                          ^^^
note: reference must be valid for the anonymous lifetime #1 defined on the block at 18:79...
  --> src/main.rs:18:80
   |>
18 |>     pub fn path_to_params(&self, path: &'a str) -> Option<HashMap<&str, &str>> {
   |>                                                                                ^
note: ...but borrowed value is only valid for the for at 22:16
  --> src/main.rs:22:17
   |>
22 |>                 for cap in route.regex.captures_iter(path) {
   |>                 ^

显然,我还有一两件事可以了解Rust的生命周期。

2 个答案:

答案 0 :(得分:3)

让我们按照生命线:

  • route.regex.captures_iter(path)创建FindCapture<'r, 't>,其中生命周期'rroute.regex的生命周期,生命周期'tpath
  • 此迭代器产生Captures<'t>,仅链接到path的生命周期
  • 其方法iter_named(&'t self)产生的SubCapture<'t>本身与path 的生命周期相关联,而cap
  • 的生命周期相关联
  • 此迭代器产生(&'t str, Option<&'t str>),以便HashMap的键和值都链接到path 的生命周期和 cap的生命周期1}}

因此,遗憾的是,HashMap不能超过cap变量,因为代码使用此变量作为“标记”来保持包含组的缓冲区存活。

我担心没有重大重组的唯一解决方案是返回HashMap<String, String>,尽管不满意。我发现单个捕获组可能匹配多次次,不确定是否要打扰它。

答案 1 :(得分:2)

Matthieu M. already explained生命状况良好。好消息是正则表达式框架识别出问题并there's a fix in the pipeline for 1.0

如提交消息中所述:

  

总是可以通过使用索引来解决这个问题。

使用Regex::capture_names可以 解决这个问题,虽然它有点嵌套:

pub fn path_to_params(&self, path: &'a str) -> Option<HashMap<&str, &str>> {
    for route in &self.routes {
        if let Some(captures) = route.regex.captures(path) {
            let mut hash = HashMap::new();
            for name in route.regex.capture_names() {
                if let Some(name) = name {
                    if let Some(value) = captures.name(name) {
                        hash.insert(name, value);
                    }
                }
            }
            return Some(hash);
        }
    }
    None
}

请注意,我还删除了外部is_match - 一次又一次运行正则表达式效率很低。