我正在编写一个应该从实现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
低 - 而且这个帧解析器函数将被调用很多次并且对性能至关重要。
Stack Overflow存在类似的问题,但没有一个能够完全回答这里的情况。
的完整性和更好的了解,下面是完整的源代码,为什么寿命问题就来了一个摘录:
数据结构声明:
// 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 {
''了'一辈子不'line'寿命相匹配。 https://play.rust-lang.org/?gist=3f510b31e0009af23d637c04660d4586&version=stable&backtrace=0。 – Stargateur
哦,我的......这么简单的改变。我假定所有'''&str'''和'''Vec <&str>'''需要具有相同的生命周期,因此'''Vec <&'a str>'''。没想到*这*是麻烦的原因。你显然有一个训练有素的眼睛 - 非常感谢你,@星际之门! – ERnsTL
不仅“a”不受限制,没有任何东西拥有从读取器获取的测试数据。你可能想使用String而不是非拥有字符串。 –