I have a struct that represents a TCP stream, over which I am recieving protobuf encoded messages. The struct impl includes a read_event
method that reads the raw data of the message into a buffer, decodes it, and returns the decoded message. I am using quick-protobuf, and the decoded struct contains references to the raw data in the buffer in order to minimize copies and allocations.
I have another function which contains a loop. Inside the loop, it repeatedly calls read_event
and checks the returned message for a specific condition. When the condition is met, it exits the function, returning the message. If the condition is not met, it discards the message and continues around the loop.
My problem is that I can't seem to return the message from this second function without angering the borrow checker.
I have made an MCVE below:
struct Event<'a> {
u8ref: &'a u8
}
struct EventStream {
buf: Vec<u8>,
}
impl EventStream {
fn read_event<'a>(&'a mut self) -> Event<'a> {
todo!()
}
}
struct Processor {
stream: EventStream,
}
impl Processor {
fn find_it<'a>(&'a mut self) -> Event<'a> {
loop {
match self.stream.read_event() {
event if *event.u8ref == 0x80 => return event,
_ => {}
}
}
}
}
fn main() {}
The real code is of course much more complex - I have left out the protobuf decoding, the stream reader is async, the loop contains other elements, and the matching condition is much more complex, but the nub of the problem is this error:
error[E0499]: cannot borrow `self.stream` as mutable more than once at a time
--> src/main.rs:22:19
|
20 | fn find_it<'a>(&'a mut self) -> Event<'a> {
| -- lifetime `'a` defined here
21 | loop {
22 | match self.stream.read_event() {
| ^^^^^^^^^^^^^^^^^^^^^^^^ `self.stream` was mutably borrowed here in the previous iteration of the loop
23 | event if *event.u8ref == 0x80 => return event,
| ----- returning this value requires that `self.stream` is borrowed for `'a`
For more information about this error, try `rustc --explain E0499`.
I have tried:
- Separating the
EventStream
from theProcessor
and passing theEventStream
in as a separate argument. - Passing the buffer in as a separate argument
How can I structure this so that I can re-use the same buffer inside the loop, returning the message that matched the condition, and of course also ensuring that borrow on the EventStream
lives as long as the returned Event
?