I have this Rust program using nom 4.2.2. (I have taken the liberty of expanding the nom parser function.)
extern crate failure;
extern crate nom;
use failure::Error;
use std::fs::File;
use std::io::Read;
fn nom_parser(i: &[u8]) -> ::nom::IResult<&[u8], String, u32> {
{ ::nom::lib::std::result::Result::Ok((i, ("foo".to_owned()))) }
}
fn my_parser(buf: &[u8]) -> Result<(&[u8], String), Error> {
Ok((buf, "foo".to_owned()))
}
fn main() -> Result<(), Error> {
let handler = |mut entries: String| { entries.clear() };
loop {
let mut buf = Vec::new();
File::open("/etc/hosts")?.read_to_end(&mut buf)?;
let res = nom_parser(&buf)?.1;
// let res = my_parser(&buf)?.1;
handler(res);
}
}
Compiling this program with rustc 1.33.0 (2aa4c46cf 2019-02-28)
yields the following issue:
error[E0597]: `buf` does not live long enough
--> nom-parsing/src/main.rs:21:26
|
21 | let res = nom_parser(&buf)?.1;
| -----------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `buf` is borrowed for `'static`
...
24 | }
| - `buf` dropped here while still borrowed
Switching to the commented out version of the parser compiles just fine. How are my_parser
and nom_parser
different? Who is borrowing buf? How should I change the program to placate the borrow checker?
let res = nom_parser(&buf)?.1;
^ here
You are using the ?
operator to propagate the error out of main
. The IResult<&[u8], String, u32>
= Result<(&[u8], String), nom::Err<&[u8], u32>>
. So in case of error the &buf
is returned as part of it, so it must stay alive even after main
function exits, but it won't because buf
is local variable inside main
.
In your case the nom_parser
never returns error, but the validation only cares about the types and function signatures.
To fix it, you should process the error somehow before propagating it up. For example:
let res = nom_parser(&buf).map_err(|_| failure::format_err!("Parsing failed!"))?.1;
Note that Err
in the IResult
is not always hard error. It could be nom::Err::Incomplete
, meaning that the parsing may succeed if more data is supplied, or nom::Err::Error
meaning that the input was not matched by the parser (so perhaps another parser in alt!
could succeed), or nom::Err::Failure
, meaning that something went really wrong during parsing. Depending on the situation, you may consider them all as failure, or handle them differently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With