【发布时间】:2020-06-22 23:10:24
【问题描述】:
我正在学习 Rust,并决定实现一块表(在 this pdf 的第 6.4 节中描述),因为它相当简单,但不平凡。
这主要是非常简单的,但我遇到了一个我无法弄清楚的问题。这是我的代码的简化版本,供参考:
use std::ops::Index;
#[derive(Debug)]
pub struct PieceTable {
// original file data: never changes
orig_buffer: Vec<u8>,
// all new data is pushed onto this buffer
add_buffer: Vec<u8>,
// the pieces that currently make up the file
pieces: Vec<Piece>,
}
#[derive(Debug, Copy, Clone)]
enum Location {
Orig,
Add,
}
#[derive(Debug, Copy, Clone)]
struct Piece {
// which buffer is this piece located at?
buf: Location,
// starting offset
start: usize,
// size of piece
length: usize,
}
impl PieceTable {
pub fn iter(&self) -> PieceTableIterator {
PieceTableIterator::new(self)
}
fn piece_buf(&self, piece: &Piece) -> &Vec<u8> {
match piece.buf {
Location::Orig => &self.orig_buffer,
Location::Add => &self.add_buffer,
}
}
fn piece_value(&self, piece: &Piece, index: usize) -> &u8 {
&self.piece_buf(piece)[index]
}
}
pub struct PieceTableIterator<'a> {
table: &'a PieceTable,
buf_iter: Option<std::slice::Iter<'a, u8>>,
piece_iter: std::slice::Iter<'a, Piece>,
}
impl<'a> PieceTableIterator<'a> {
fn new(table: &PieceTable) -> PieceTableIterator {
let mut iter = table.pieces.iter();
let piece = iter.next();
let buf_iter = piece.map(|p| table.piece_buf(p).iter());
PieceTableIterator {
table: table,
buf_iter: buf_iter,
piece_iter: iter,
}
}
}
impl<'a> Iterator for PieceTableIterator<'a> {
type Item = u8;
fn next(&mut self) -> Option<u8> {
if self.buf_iter.is_none() {
return None;
}
match self.buf_iter {
Some(ref mut iter) => {
iter.next()
.or_else(|| {
self.piece_iter.next().and_then(|p| {
let mut buf = self.table.piece_buf(p)[p.start..(p.start + p.length)]
.iter();
let item = buf.next();
self.buf_iter = Some(buf);
item
})
})
.map(|b| *b)
}
None => None,
}
}
}
fn main() {
let table = PieceTable {
orig_buffer: vec![1, 2, 3],
add_buffer: vec![4, 5, 6],
pieces: vec![Piece {
buf: Location::Orig,
start: 0,
length: 2,
},
Piece {
buf: Location::Add,
start: 0,
length: 3,
},
Piece {
buf: Location::Orig,
start: 2,
length: 1,
}],
};
// shoud print 1, 2, 4, 5, 6, 3
for i in table.iter() {
println!("{}", i);
}
}
我正在尝试为这个结构构建一个迭代器。我可以通过在迭代器中保留一个索引来非常低效地做到这一点,但是对于每个.next() 调用,我必须遍历所有部分。相反,我宁愿让我的迭代器存储片段的迭代器和当前片段的缓冲区切片的迭代器。我的问题(我尝试了几种不同的方法)是我不断遇到终身问题。我当前的代码给了我错误:
:76:30: 84:22 error: closure requires unique access to `self` but `self.buf_iter.0` is already borrowed [E0500]
我想我明白了,但我不确定如何解决。我已经尝试了当前代码的一些变体,它们都遇到了类似的问题。
【问题讨论】:
标签: rust