I want to implement a custom UDP based protocol. However, I am running into problems implementing it with a good API. Here's a short example of approximately how I'd like it to work:
let host = Host::new(/* protocol config, port number to listen on etc. */)
let connection = host.connect(address, /* connection config */)
connection.send(bytes)
I'd like the connect
function to return a Connection
object that can be used to send packets. Because the Host
owns the socket however, the sending and receiving has to be done via the Host
:
let msg = host.service() // Do IO stuff
Here's what I tried (this is the simplest version that represents the problem):
struct Connection {
value: u32 // some placeholder
}
struct Host {
connections: Vec<Connection>
}
impl Host {
fn new() -> Host {
Host {
connections: Vec::new()
}
}
fn connect(&mut self, value: u32) -> &mut Connection {
self.connections.push(Connection { value });
let l = self.connections.len();
self.connections.get_mut(l-1).unwrap() // very hacky
}
fn service(&self){
// do something with the connections
}
}
fn main() {
let mut host = Host::new();
let conn = host.connect(1);
// in this specific case, I could just drop `conn` right here.
// However, in reality, I will want it to stick around
// for much longer, across .service() calls
host.service();
}
As you can see, there are a number of issues:
- I have a situation where two things need a mutable borrow at the same time. I have tried solving this with Rc, but it does not really solve the "double borrow" problem.
- adding something to a list while keeping a reference safely without resorting to the .length() hack