Search code examples
filerustborrow-checkerborrowing

Reading bytes from a file and parsing them with `pom` parser library


I'm trying to write a parser with pom, which is great - no problems writing the parsers and feeding in string literal as test data. However, when I try to run it bytes from a file, it chokes;

108 |     fn parse_files() -> Result<(), Box<dyn Error>> {
109 |         let byte_vec: Vec<u8> = std::fs::read("assets/valid_so_far.idl")?;
110 |         let byte_slice: &[u8] = &byte_vec;
    |                                 ^^^^^^^^^ borrowed value does not live long enough
111 |         let idl_parser = idl();
112 |         let parse_result = idl_parser.parse(byte_slice)?;
    |                            ---------------------------- argument requires that `byte_vec` is borrowed for `'static`
113 |         
114 |         Ok(())
115 |     }
    |     - `byte_vec` dropped here while still borrowed

I don't see what's going wrong here. I can't interpret the compiler error here and I don't understand why the lifetimes aren't OK here.

The parse function on line 109 has this signature:

fn parse(&self, input: &'a [I]) -> Result<O>

pub type Result<O> = ::std::result::Result<O, Error>;

Solution

  • no problems writing the parsers and feeding in string literal as test data.

    This works because all string literals have the 'static lifetime. When you switch to read from a file instead, the latent 'static is gone. The behavior of the code actually changes so that it triggers the error.

    The question is then why your parser implementation expects a 'static input in the first place. I suspect that the example given in the pom read-me file is to be blamed here. For example it has the following code:

    use pom::Parser;
    
    fn space() -> Parser<u8, ()> {
        one_of(b" \t\r\n").repeat(0..).discard()
    }
    

    pom::Parser<u8, ()> is actually an alias for pom::parser::Parser<'static, u8, ()>. If it were to be written as:

    use pom::parser::Parser;
    
    fn space<'a>() -> Parser<'a, u8, ()> {
        one_of(b" \t\r\n").repeat(0..).discard()
    }
    

    then it should be able to handle both 'static and non-'static input. Make similar changes to your parser code and it will work again.