I'm talking to some hardware over a link with kind of a publisher/subscriber model. In C++, I did subscriptions with RAII to remember to always unsubscribe, but I can't seem to get the ownerships/borrows right in rust.
Naively, this is something like what I would like to do. send
and receive
probably needs to be &mut self
, so as I understand, Subscription
needs mutable access to the Transport
.
struct Transport;
impl Transport {
pub fn send(&mut self, cmd: &str) { unimplemented!() }
pub fn subscribe(&mut self, cmd: &str) -> Subscription {
self.send("subscribe-with-params");
Subscription { trans: &mut self }
}
}
struct Subscription {
trans: &mut Transport,
}
impl Drop for Subscription {
fn drop(&mut self) {
self.trans.send("unsubscribe-with params");
}
}
impl Subscription {
fn receive(&mut self) -> &[u8] { /*blocking wait for data*/ }
}
fn test(t: Transport) {
// Need to subscribe before command, as command might generate status messages
let mut status_sub = t.subscribe("status-message");
{
let mut short_lived_sub = t.subscribe("command_reply");
t.send("command");
short_lived_sub.receive(); // Wait for ack
}
loop {
println!("{:?}", status_sub.receive());
/*processing of status */
}
}
There are at least two problems here. One is how Subscription
should keep some reference to it's "parent", the Transport
, and another is the problem in fn test
that I can't borrow Transport
twice for two different subscriptions.
I have a feeling that I'm kind of asking the wrong question here, so maybe there's a good way of approaching this in a different way entirely?