I am trying to program an application that listens for requests on a socket and then adds them onto a queue to be processed. Part of my code goes as follows:
pub struct Middleware {
listener: TcpListener,
queue: Vec<String>,
servers: Vec<String>,
}
impl Middleware {
pub fn run(&mut self) {
for stream in self.listener.incoming() {
let mut stream = stream.unwrap();
let mut buffer = vec![0u8; 512];
stream.read(&mut buffer).unwrap();
self.queue.push(String::from_utf8(buffer).unwrap());
}
}
}
Yet if I try to abstract some of the code in run()
into a function (literally just copy/paste):
impl Middleware {
pub fn run(&mut self) {
for stream in self.listener.incoming() {
let mut stream = stream.unwrap();
self.handle_client(stream);
}
}
fn handle_client(&mut self, mut stream: TcpStream) {
let mut buffer = vec![0u8; 512];
stream.read(&mut buffer).unwrap();
self.queue.push(String::from_utf8(buffer).unwrap());
}
}
I get the following error message:
cannot borrow `*self` as mutable because `self.listener` is also borrowed as immutable
--> src/lib.rs:21:13
|
19 | for stream in self.listener.incoming() {
| ------------- immutable borrow occurs here
20 | let mut stream = stream.unwrap();
21 | self.handle_client(stream);
| ^^^^ mutable borrow occurs here
22 | }
| - immutable borrow ends here
From what I understand, self.listener.incoming()
actually borrows not only the listener "field" but the entire struct. And then, as we cannot have any mutable borrow simultaneously with an immutable borrow, the compiler complains. However, I have to make self
mutable in handle_client()
, otherwise I cannot push anything on its queue.
I have been thinking about how to structure the code differently to overcome this problem but can't seem to find a solution without changing my Middleware
struct (as in removing some fields, etc).
Is it possible to somehow structure the code to use a function (like in my second code snippet)?