Trying to work with nom and iterate over my result, but I can't figure out why this borrowed value doesn't live long enough. Still new to Rust and have been head-banging for hours. Would appreciate help!
use anyhow;
use nom::{
bytes::complete::{tag, take},
character::complete::newline,
combinator::rest,
multi::separated_list1,
sequence::separated_pair,
IResult,
};
pub fn parse(raw: String) -> anyhow::Result<()> {
let (_, lines) = parse_multiline(&raw)?;
for line in lines.iter() {
let (label, value) = line;
println!("label: {}, value: {}", label, value);
}
Ok(())
}
fn parse_multiline(i: &str) -> IResult<&str, Vec<(&str, &str)>> {
separated_list1(
newline,
separated_pair(
take(14usize),
tag(" : "),
rest,
),
)(i)
}
And the error:
error[E0597]: `raw` does not live long enough
--> src/parser/person.rs:12:38
|
12 | let (_, lines) = parse_multiline(&raw)?;
| ----------------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `raw` is borrowed for `'static`
...
21 | }
| - `raw` dropped here while still borrowed
In parse_multiline()
you return IResult<&str, Vec<(&str, &str)>>
. This means that if your parse_multiline()
fails, then it returns nom::Err
<
nom::error::Error
<&str>>
which has a reference to i
/&raw
.
Thus in parse()
, parse_multiline(raw)?
propagates that error further, which would return a reference to raw
, which would not live long enough.
If you want to retain fn parse(raw: String)
, then the you can use Result::map_err()
and then nom::Err::map()
, to convert the &str
into an owned String
on error.
// nom = "6.1"
use nom::error::Error;
pub fn parse(raw: String) -> anyhow::Result<()> {
let (_, lines) = parse_multiline(&raw)
.map_err(|err| err.map(|err| Error::new(err.input.to_string(), err.code)))?;
// ...
}