I'm writing a library that should read from something implementing the BufRead trait; a network data stream, standard input, etc. The first function is supposed to read a data unit from that reader and return a populated struct filled mostly with &'a str values parsed from a frame from the wire.
Here is a minimal version:
mod mymod {
    use std::io::prelude::*;
    use std::io;
    pub fn parse_frame<'a, T>(mut reader: T)
    where
        T: BufRead,
    {
        for line in reader.by_ref().lines() {
            let line = line.expect("reading header line");
            if line.len() == 0 {
                // got empty line; done with header
                break;
            }
            // split line
            let splitted = line.splitn(2, ':');
            let line_parts: Vec<&'a str> = splitted.collect();
            println!("{} has value {}", line_parts[0], line_parts[1]);
        }
        // more reads down here, therefore the reader.by_ref() above
        // (otherwise: use of moved value).
    }
}
use std::io;
fn main() {
    let stdin = io::stdin();
    let locked = stdin.lock();
    mymod::parse_frame(locked);
}
An error shows up which I cannot fix after trying different solutions:
error: `line` does not live long enough
  --> src/main.rs:16:28
   |
16 |             let splitted = line.splitn(2, ':');
   |                            ^^^^ does not live long enough
...
20 |         }
   |         - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the body at 8:4...
  --> src/main.rs:8:5
   |
8  | /     {
9  | |         for line in reader.by_ref().lines() {
10 | |             let line = line.expect("reading header line");
11 | |             if line.len() == 0 {
...  |
22 | |         // (otherwise: use of moved value).
23 | |     }
   | |_____^
The lifetime 'a is defined on a struct and implementation of a data keeper structure because the &str requires an explicit lifetime. These code parts were removed as part of the minimal example.
BufReader has a lines() method which returns Result<String, Err>. I handle errors using expect or match and thus unpack the Result so that the program now has the bare String. This will then be done multiple times to populate a data structure.
Many answers say that the unwrap result needs to be bound to a variable otherwise it gets lost because it is a temporary value. But I already saved the unpacked Result value in the variable line and I still get the error.
- How to fix this error - could not get it working after hours trying. 
- Does it make sense to do all these lifetime declarations just for - &strin a data keeper struct? This will be mostly a readonly data structure, at most replacing whole field values.- Stringcould also be used, but have found articles saying that- Stringhas lower performance than- &str- and this frame parser function will be called many times and is performance-critical.
Similar questions exist on Stack Overflow, but none quite answers the situation here.
For completeness and better understanding, following is an excerpt from complete source code as to why lifetime question came up:
Data structure declaration:
// tuple
pub struct Header<'a>(pub &'a str, pub &'a str);
pub struct Frame<'a> {
    pub frameType: String,
    pub bodyType: &'a str,
    pub port: &'a str,
    pub headers: Vec<Header<'a>>,
    pub body: Vec<u8>,
}
impl<'a> Frame<'a> {
    pub fn marshal(&'a self) {
        //TODO
        println!("marshal!");
    }
}
Complete function definition:
pub fn parse_frame<'a, T>(mut reader: T) -> Result<Frame<'a>, io::Error> where T: BufRead {
 
    