I'm a Rust beginner, writing a nom parser that can parse lines that are colon-separated KEY: VALUE
s. I made a base kv
parser with named_args
that can parse a key-value pair:
named_args!(kv<'a>(key: &'a str)<&'a str, &'a str>,
do_parse!(
tag_s!(key) >>
tag_s!(":") >>
space0 >>
value: rest >>
(value)
)
);
I put the lifetimes in there to please the compiler.
I've made these two parsers from it:
named!(name<&str,&str>,
call!(kv, "NAME")
);
named!(get_dimension<&str, i64>,
map_res!(call!(kv, "DIMENSION"), str::parse::<i64>)
);
To test these, I was writing a generic wrapper, which calls one of these functions with a KEY: {YOUR_VALUE}
string, and expects YOUR_VALUE
back:
fn test_kv<G: Display + Debug + PartialEq>(
kvfunc: fn(&str) -> Result<(&str, G), Err<&str>>,
key: &str,
value: G,
) {
assert_eq!(kvfunc(&format!("{}: {}", key, value)), Ok(("", value)));
}
This works fine:
#[test]
fn test_dimension() {
test_kv(get_dimension, "DIMENSION", 8)
}
But not with the name
parser:
#[test]
fn test_name() {
test_kv(name, "NAME", "some_name")
}
The compiler gives me:
71 | test_kv(name, "NAME", "some_name")
| ^^^^ expected concrete lifetime, found bound lifetime parameter
|
= note: expected type `for<'r> fn(&'r str) -> std::result::Result<(&'r str, _), nom::Err<&'r str>>`
found type `for<'r> fn(&'r str) -> std::result::Result<(&'r str, &'r str), nom::Err<&'r str>> {name}`
This confuses me. Doesn't Result<&str, &str>
fit in Result<&str, _>
?
Since it works with the map_res
'd version, I assume that map_res
returns a different value, maybe with a different lifetime.
I think I may have to change the lifetime definitionss of my kv
parser, but I'm completely lost as to how/which ones to choose.