我希望将匹配中的所有命名组提取到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的生命周期。
答案 0 :(得分:3)
让我们按照生命线:
route.regex.captures_iter(path)
创建FindCapture<'r, 't>
,其中生命周期'r
是route.regex
的生命周期,生命周期't
是path
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
- 一次又一次运行正则表达式效率很低。