No se puede dividir una cadena en segmentos de cadena con vidas explícitas porque la cadena no dura lo suficiente
Estoy escribiendo una biblioteca que debería leer algo implementando elBufRead
rasgo; un flujo de datos de red, entrada estándar, etc. Se supone que la primera función lee una unidad de datos de ese lector y devuelve una estructura poblada llena principalmente de&'a str
valores analizados desde un marco desde el cable.
Aquí hay una versión mínima:
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);
}
Aparece un error que no puedo solucionar después de probar diferentes soluciones:
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 | | }
| |_____^
La vida'a
se define en una estructura e implementación de una estructura de guardián de datos porque el&str
requiere una vida explícita Estas partes del código se eliminaron como parte del ejemplo mínimo.
BufReader
tiene unlines()
método que devuelveResult<String, Err>
. Manejo errores usandoexpect
omatch
y así desempacar elResult
para que el programa ahora tenga el desnudoString
. Esto se hará varias veces para completar una estructura de datos.
Muchas respuestas dicen que elunwrap
el resultado debe estar vinculado a una variable; de lo contrario, se pierde porque es un valor temporal. Pero ya guardé el desempaquetadoResult
valor en la variableline
y sigo recibiendo el error
Cómo solucionar este error: no pude hacerlo funcionar después de horas de intentarlo.
¿Tiene sentido hacer todas estas declaraciones de por vida solo por&str
en una estructura de guardián de datos? Esto será principalmente una estructura de datos de solo lectura, como máximo reemplazando los valores de campo completo.String
también podría usarse, pero he encontrado artículos que dicen queString
tiene un rendimiento menor que&str
- y esta función del analizador de cuadros se llamará muchas veces y es crítica para el rendimiento.
Existen preguntas similares en Stack Overflow, pero ninguna responde a la situación aquí.
Para completar y comprender mejor, el siguiente es un extracto del código fuente completo de por qué surgió la pregunta de por vida:
Declaración de estructura de datos:
// 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!");
}
}
Definición de función completa:
pub fn parse_frame<'a, T>(mut reader: T) -> Result<Frame<'a>, io::Error> where T: BufRead {