Может быть, следующая программа дает подсказки для тех, у кого также есть первые проблемы с жизнями:
у библиотеку, которая должна читать что-то, реализующееBufRead
черта характера; сетевой поток данных, стандартный ввод и т. д. Предполагается, что первая функция считывает блок данных из этого считывателя и возвращает заполненную структуру, заполненную в основном&'a str
значения разбираются из кадра с провода.
Вот минимальная версия:
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);
}
Появляется ошибка, которую я не могу исправить после попытки разных решений:
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 | | }
| |_____^
Время жизни'a
определяется в структуре и реализации структуры хранителя данных, потому что&str
требует явного времени жизни. Эти части кода были удалены как часть минимального примера.
BufReader
имеетlines()
метод, который возвращаетResult<String, Err>
, Я обрабатываю ошибки, используяexpect
или жеmatch
и, таким образом, распаковатьResult
так что программа теперь имеет голоеString
, Это будет сделано несколько раз для заполнения структуры данных.
Многие ответы говорят, чтоunwrap
результат должен быть связан с переменной, иначе он теряется, потому что это временное значение. Но я уже сохранил распакованныйResult
значение в переменнойline
и я все еще получаю ошибку.
Как исправить эту ошибку - не смог заставить ее работать после нескольких часов попыток.
Имеет ли смысл делать все эти пожизненные объявления только для&str
в структуре хранителя данных? Это будет в основном структура данных только для чтения, в большинстве случаев заменяющая целые значения полей.String
также может быть использован, но нашел статьи о том, чтоString
имеет более низкую производительность, чем&str
- и эта функция синтаксического анализа кадров будет вызываться много раз и критична для производительности.
Подобные вопросы существуют в отношении переполнения стека, но ни один из них не совсем отвечает ситуации здесь.
Для полноты и лучшего понимания ниже приводится выдержка из полного исходного кода о том, почему возник вопрос на всю жизнь:
Объявление структуры данных:
// 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!");
}
}
Полное определение функции:
pub fn parse_frame<'a, T>(mut reader: T) -> Result<Frame<'a>, io::Error> where T: BufRead {