gpt4 book ai didi

rust - 如何通过匹配处理 Rust 中的多个可变借用?

转载 作者:行者123 更新时间:2023-11-29 08:00:54 26 4
gpt4 key购买 nike

我正在尝试使用 quick-xml 封装一个 XML 解析器,该解析器在条目中采用一些特定的 XML。主要代码如下:

pub struct GPXParser<B: BufRead> {
reader: Reader<B>,
buff: Vec<u8>,
}

impl<B> GPXParser<B> {
pub fn read_next<a>(&mut self) -> Result<XMLCache, Error> {
match self.reader.read_event(&mut self.buff) {
Ok(XMLEvent::Start(ref e)) if e.name() == b"wpt" => {
self.read_next_wpt() // --> Multiple mutable borrows error
}
_ => Err(Error::NoCaches),
}
}

fn read_next_wpt(&mut self) -> Result<XMLCache, Error> {
match self.reader.read_event(&mut self.buff) {
_ => Err(Error::NoCaches),
}
}
}

然后我读了这个topic在 rust-lang.org 上,提到:

idiomatic Rust code typically avoids holding long-lived references to mutable object internals and favors alternate approaches that use immutable references or independent values

我尝试使用中间 buff 元素改变我的方法:

pub struct GPXParser<B: BufRead> {
reader: Reader<B>,
}

impl<B> GPXParser<B> {
pub fn read_next<a>(&mut self) -> Result<XMLCache, Error> {
let mut buff: Vec<u8> = Vec::new();

match self.reader.read_event(&mut buff) {
Ok(XMLEvent::Start(ref e)) if e.name() == b"wpt" => {
self.read_next_wpt(&mut buff) // --> Multiple mutable borrows error
}
_ => Err(Error::NoCaches),
}
}

fn read_next_wpt(&mut self, buff: &mut Vec<u8>) -> Result<XMLCache, Error> {
match self.reader.read_event(buff) {
_ => Err(Error::NoCaches),
}
}
}

我没有改变方法。

我试图将 match 语句分成两行:

pub fn read_next<a>(&mut self) -> Result<XMLCache, Error> {
let result = self.reader.read_event(&mut self.buff);
match result {
Ok(XMLEvent::Start(ref e)) if e.name() == b"wpt" => self.read_next_wpt(),
_ => Err(Error::NoCaches),
}
}

但我得到了同样的错误:

error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/gpx/mod.rs:34:17
|
31 | let result = self.reader.read_event(&mut self.buff);
| --------- first mutable borrow occurs here
...
34 | self.read_next_wpt()
| ^^^^ second mutable borrow occurs here
...
39 | }
| - first borrow ends here

有没有办法在不同的方法调用周围使用相同的缓冲区?

一些生命应该进入游戏吗?

如果不是,那么解决此问题的惯用 Rust 方法是什么?

最佳答案

问题来自 prototype for read_event 中的 'b 生命周期:

pub fn read_event<'a, 'b>(
&'a mut self,
buf: &'b mut Vec<u8>
) -> Result<Event<'b>>

这将缓冲区的生命周期与返回值的生命周期联系起来,因此只要结果还存在,您就不能重复使用缓冲区。当您不想递归并仅在使用完结果后才递归时,您可以通过提早返回来绕过它:

pub fn read_next<a>(&mut self) -> Result<XMLCache, Error> {
match self.reader.read_event(&mut self.buff) {
Ok(XMLEvent::Start(ref e)) if e.name() == b"wpt" => (),
_ => { return Err(Error::NoCaches) },
}
self.read_next_wpt()
}

如果您想添加更多案例,您必须首先从结果中提取您希望使用的任何相关信息,包括选择要调用的方法所需的任何信息,然后在调用该方法之前让结果超出范围.例如:

pub fn read_next<a>(&mut self) -> Result<XMLCache, Error> {
let next_method = match self.reader.read_event(&mut self.buff) {
Ok(XMLEvent::Start(ref e)) if e.name() == b"wpt" => GPXParser<B>::read_next_wpt,
Ok(XMLEvent::Start(ref e)) if e.name() == b"foo" => GPXParser<B>::read_next_foo,
_ => { return Err(Error::NoCaches) },
}
next_method(self)
}

或者,如果性能影响小到可以接受(您应该对其进行测量以支持您的决定),则每次只使用不同的缓冲区可能会更容易。


下面的原始答案供引用:

尝试将 read_event 和匹配拆分成单独的行:

let result = self.reader.read_event(&mut self.buff);
match result {
...
}

你的问题是缓冲区是为整个匹配表达式可变借用的,所以你不能在匹配臂内重新借用缓冲区。通过将代码分成两行,缓冲区只为第一个表达式 (let result=...) 借用,并且可以在匹配中再次借用。

当非词汇生命周期变得稳定时,这可能会在未来得到解决。

关于rust - 如何通过匹配处理 Rust 中的多个可变借用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50343279/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com