我正在尝试实现一个文件行读取器,它不会进行太多的检查和分配来加速某些文件的读取。
这应该是有效的,但是编译器抱怨借用 self.buffer 作为可变的,而在 read_line 方法的开头仍然借用为不可变的。这个问题似乎与生命周期有关,但我无法向编译器解释第一个借用被删除并且与 None => arm 无关了。
struct FastFileLinesReader<B: BufRead> {
stream: B,
buffer: Vec<u8>,
cursor: usize,
}
impl<B: BufRead> FastFileLinesReader<B> {
fn new(stream: B) -> Self {
Self {
stream,
buffer: vec![1024],
cursor: 0,
}
}
fn read_line(&mut self) -> Option<&[u8]> {
let line = {
let remainder = &self.buffer[self.cursor..];
remainder.split_once(|v| *v == b'\n' as u8)
};
match line {
Some((line, _)) => {
self.cursor += line.len() + 1;
return Some(line);
}
None => {
self.buffer.copy_within(self.cursor.., 0);
self.cursor = 0;
let n = self.stream.read(&mut self.buffer[self.cursor..]).ok()?;
if n == 0 {
return None;
}
return self.read_line();
}
};
}
}
错误:
error[E0502]: cannot borrow `self.buffer` as mutable because it is also borrowed as immutable
--> src/bin/main.rs:110:17
|
99 | fn read_line(&mut self) -> Option<&[u8]> {
| - let's call the lifetime of this reference `'1`
100 | let line = {
101 | let remainder = &self.buffer[self.cursor..];
| ----------- immutable borrow occurs here
...
107 | return Some(line);
| ---------- returning this value requires that `self.buffer` is borrowed for `'1`
...
110 | self.buffer.copy_within(self.cursor.., 0);
@isaactfa 是对的,这种情况是借用检查器的一个已知限制,它错误地认为提前返回与函数的其余部分重叠。
在这种情况下,您可以通过避免从
.split_once
获得的引用来回避问题,而只需使用索引即可:
fn read_line(&mut self) -> Option<&[u8]> {
let newline = self.buffer[self.cursor..].iter().position(|v| *v == b'\n' as u8);
if let Some(idx) = newline {
self.cursor += idx + 1;
return Some(&self.buffer[self.cursor..][..idx]);
} else {
self.buffer.copy_within(self.cursor.., 0);
self.cursor = 0;
let n = self.stream.read(&mut self.buffer[self.cursor..]).ok()?;
if n == 0 {
return None;
}
return self.read_line();
}
}