I'm quite new to Rust, I'm mainly a C#, javascript and python developer, so I like to approach things in a OOP way, however I still can't wrap my head around ownership in rust. Especially when it comes to OOP.
I'm writing a TCP server. I have a struct that contains connections (streams) and I read the sockets asynchronously using the mio crate. I understand what the error is telling me, but I have no clue how to fix it. I tried changing the read_message method into a function (without the reference to self), which worked, but the problem with this is that I'll need to access the connections and whatnot from the struct (to relay messages between sockets for example), so this workaround won't be plausible in later versions. Is there an easy fix for this, or is the design inherently flawed?
Here's a snippet that shows what my problem is:
let sock = self.connections.get_mut(&token).unwrap();
loop {
match sock.read(&mut msg_type) {
Ok(_) => {
self.read_message(msg_type[0], token);
}
}
}
fn read_message(&mut self, msg_type: u8, token: Token) {
let sock = self.connections.get_mut(&token).unwrap();
let msg_type = num::FromPrimitive::from_u8(msg_type);
match msg_type {
Some(MsgType::RequestIps) => {
let decoded: MsgTypes::Announce = bincode::deserialize_from(sock).unwrap();
println!("Public Key: {}", decoded.public_key);
}
_ => unreachable!()
}
}
You are holding a mutable borrow on
sock
, which is part ofself
, at the moment you try to callself.read_message
. Since you indicated thatread_message
needs mutable access to all ofself
, you need to make sure you don't have a mutable borrow onsock
anymore at that point.Fortunately, thanks to non-lexical lifetimes in Rust 2018, that's not hard to do; simply fetch
sock
inside the loop:Assuming
sock.read
doesn't return anything that holds a borrow onsock
, this should let the mutable borrow onsock
be released before callingself.read_message
. It needs to be re-acquired in the next iteration, but seeing as you're doing network I/O, the relative performance penalty of a singleHashMap
(?) access should be negligible.(Due to lack of a minimal, compileable example, I wasn't able to test this.)