为了更好地了解Rust,我正在构建一个简单的文本编辑器,并具有以下结构:
struct File {
rows: Vec<Row>,
filename: Option<String>
}
impl File {
fn row(&self, index: u16) -> &Row{
&self.rows[index as usize]
}
}
struct Row {
string: String,
}
struct EditorState {
file: File,
}
如您所见,我将编辑器的状态保留在一个结构中,该结构引用该文件,该文件包含许多行,其中包含一个字符串(这些结构中的每一个都有更多字段,但是我删除了与问题无关的东西
现在,我想使行可编辑并添加以下内容:
impl Row {
fn insert(&mut self, at: u16, c: char) {
let at = at as usize;
if at >= self.string.len() {
self.string.push(c);
} else {
self.string.insert(at, c)
}
}
}
这是我尝试更新行的方法:
//In the actual functon, I am capturing the keypress,
//get the correct row from the state and pass it and the pressed
// char to row.insert
fn update_row(mut state: &mut EditorState) {
let row = &state.file.row(0);
row.insert(0, 'a');
}
无法编译:
error[E0596]: cannot borrow `*row` as mutable, as it is behind a `&` reference
从错误中,我可以看到问题是Row应该是可变的,因此我可以对其进行编辑(这很有意义,因为我正在对它的String进行突变)。我无法弄清楚a)如何能够在此处对字符串进行突变,以及b)如何在没有row
的情况下总是返回可变引用的情况下进行此操作,因为在所有其他情况下,我都在调用{{1 }}读取一行,而不是将其写入。
答案 0 :(得分:2)
这是File
惯用的实现:
impl File {
fn row(&self, index: usize) -> Option<&Row> {
self.rows.get(index)
}
fn row_mut(&mut self, index: usize) -> Option<&mut Row> {
self.rows.get_mut(index)
}
}
这里的注意事项:
index
超出范围,您的实现将会感到恐慌。处理此问题的惯用方式是返回一个Option,get
和get_mut
允许您免费获取。u16
是任意的。在那种情况下,我不会依赖类型的最大值,而是会使用一个常量来使意图更清晰。答案 1 :(得分:1)
您想要的是不可能的。您将必须编写两个函数(请注意,我将u16
替换为usize
-没有理由将自己限制为每行65536个字符):
fn row(&self, index: usize) -> &Row {
&self.rows[index]
}
fn row_mut(&mut self, index: usize) -> &mut Row {
&mut self.rows[index]
}
请注意,这是所有Rust代码中的通用模式。例如,Vec
具有get(idx)
和get_mut(idx)
。