我有下一个代码:
struct Tokenizer {
reader: BufReader<File>,
buf: Vec<u8>,
token: String
}
impl Tokenizer {
fn new(path: &PathBuf) -> Tokenizer {
let file = File::open(path).expect("Unable to open file!");
Tokenizer {
reader: BufReader::new(file),
buf: Vec::<u8>::new(),
token: String::new()
}
}
fn next(&mut self) -> bool {
if self.buf.len() == 0 {
if self.reader.read_until(b'\n', &mut self.buf)
.expect("Unable to read file") == 0 {
return false;
}
}
let s = String::from_utf8(self.buf).expect("Unable to read file");
let mut start: i8 = -1;
let mut end: i8 = -1;
for (i, c) in s.char_indices() {
if start == -1 {
if !c.is_whitespace() {
start = i as i8;
}
} else {
if c.is_whitespace() {
end = i as i8;
}
}
}
self.token = s.chars().skip(start as usize).take((end - start) as usize).collect();
self.buf = s.into_bytes();
self.buf.clear();
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
但由于错误而不起作用:
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\parser.rs:28:35
|
28 | let s = String::from_utf8(self.buf).expect("Unable to read file");
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)
我读过类似的问题,建议使用,swap但我不知道它会如何帮助我。如何修复这个错误,为什么它不能编译?
String::from_utf8按值获取其参数,这意味着它不仅仅使用它所消耗的 vec 。
但在这里它不能消耗输入:因为self只是一个可变借用self.buf最多是一个可变借用(又名&mut Vec<u8>),因此签名不匹配。这是因为String::from_utf8将检查输入是否有效,然后将其重新解释为有效字符串,避免新分配。
有两种简单的方法可以解决这个问题,我可以在这里看到:
最简单的方法是使用一个将引用作为输入的函数,例如str::from_utf8,这将在内部分配一个新的 String 以返回数据,因此效率稍低但更方便。
另一种选择——以及swap你得到的建议——是将数据移出借用:如果你有一个可变借用,你不能使用, self.buf但你可以用一个新的(拥有的)缓冲区替换它。
swap执行此操作并返回旧值,因此您可以将 的当前内容交换self.buf为全新的(空)向量,并取出以前称为 的向量self.buf,现在由您拥有(而不是self),因此可以使用。
它在这里的样子是:
let mut buf = Vec::new();
swap(&mut buf, self.buf);
// here we now consume the swapped buf
let s = String::from_utf8(buf).expect("Unable to read file");
let mut start: i8 = -1;
let mut end: i8 = -1;
for (i, c) in s.char_indices() {
if start == -1 {
if !c.is_whitespace() {
start = i as i8;
}
} else {
if c.is_whitespace() {
end = i as i8;
}
}
}
self.token = s.chars().skip(start as usize).take((end - start) as usize).collect();
self.buf = s.into_bytes();
self.buf.clear();
return true;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4497 次 |
| 最近记录: |