我编写了以下代码而没有预期借用检查器:
impl<C: Consumer> Transmit<C> {
pub fn next(&mut self) -> Option<u8> {
use State::*;
match self.state {
InPkt(pkt_left, 0) => {
self.reader.read_bytes_maybe(1, |bytes| {
// ^^^^
let len = bytes[0];
if len < pkt_left {
self.crc += len;
// ^^^^
self.state = InPkt(pkt_left - len, len);
(1, len)
} else {
self.state = AfterPkt;
(0, self.crc)
}
}).or_else(|| {
self.state = AfterPkt;
Some(self.crc)
})
}
InPkt(pkt_left, len_left) => {
self.reader.read_byte().map(|b| {
self.state = InPkt(pkt_left, len_left - 1);
self.crc += b;
b
})
}
AfterPkt => {
self.crc = 0;
self.state = InPkt(<u8>::max_value(), 0);
Some(0)
}
}
}
}
pub struct Transmit<R> {
pub state: State,
pub crc: u8, // simplified
pub reader: R
}
#[derive(Clone, Copy)]
pub enum State {
InPkt(u8, u8),
AfterPkt,
}
pub trait Consumer {
fn read_byte(&mut self) -> Option<u8>;
// implemented on a buffer, with read_bytes_maybe you can peek at some bytes
// (if there are enough) and then decide how many to actually consume
fn read_bytes_maybe<R>(&mut self, u8, impl FnOnce(&[u8]) -> (u8, R)) -> Option<R>;
}
正如您可以在this playground中尝试一样,编译器会抱怨
error[E0500]: closure requires unique access to `self` but `self.reader` is already borrowed --> src/main.rs:7:48 | 7 | self.reader.read_bytes_maybe(1, |bytes| { | ----------- borrow occurs here ^^^^^^^ closure construction occurs here ... 11 | self.crc += len; | ---- borrow occurs due to use of `self` in closure ... 19 | }).or_else(|| { | - borrow ends here
我该如何解决这个问题?我的read_bytes_maybe
设计是否有缺陷?我应该不使用闭包但有两个方法,一个用于创建具有内部状态的Read
结构,第二个用于使用该结构?
我找到了两个&#34;解决方案&#34;,第一个避免在闭包中使用整个self
但是单独借用字段:
InPkt(pkt_left, 0) => {
let crc = &mut self.crc;
let state = &mut self.state;
self.reader.read_bytes_maybe(1, |bytes| {
let len = bytes[0];
if len < pkt_left {
*crc += len;
*state = InPkt(pkt_left - len, len);
(1, len)
} else {
*state = AfterPkt;
(0, *crc)
}
}).or_else(|| {
*state = AfterPkt;
Some(*crc)
})
}
和第二个使用Option
作为闭包返回值来对if
的比较结果进行编码,然后仅更改state
/ crc
:
InPkt(pkt_left, 0) => {
if let Some(len) = self.reader.read_bytes_maybe(1, |bytes| {
let len = bytes[0];
if len < pkt_left {
(1, Some(len))
} else {
(0, None)
}
}).unwrap_or(None) {
self.crc += len;
self.state = InPkt(pkt_left - len, len);
Some(len)
} else {
self.state = AfterPkt;
Some(self.crc)
}
}
我不喜欢他们中的任何一个,他们认为我是非惯用的,比原来更难理解。