dimanche 5 novembre 2023

Generic UDP message receiver design in Rust

I am having difficulty coming up with a networking design in Rust. Essentially, I want to be able to receive all kinds of messages from different udp sockets. All messages implement the following trait:

pub trait Message {
    fn encode(&self) -> Vec<u8>;
    fn decode(buf: &[u8]) -> Self;
}

I would like to use mio in order to receive and produce registered messages from multiple sockets on a single thread. Let's call the object that creates such a thread a MessageGroup. This struct has two fundamental functions:

fn add_receiver<T: Message>(&mut self,socket_addr: SocketAddr) -> Receiver<T>;
fn run(&mut self);

This would allow me to use MessageGroup as follows:

pub struct Foo(u32);
impl Message for Foo {
  // ...
}

pub struct Bar(usize);
impl Message for Bar {
  // ...
}

fn main() {
  // ...
  let mut grp = MessageGroup();
  let foo_receiver = grp.add_receiver::<Foo>("127.0.0.1:9001".parse().unwrap());
  let bar_receiver = grp.add_receiver::<Bar>("127.0.0.1:9002".parse().unwrap());
  grp.run();
  select! {
    recv(foo_receiver) -> msg => {
       println!("{}", msg.0);
    }
    recv(bar_receiver ) -> msg => {
       println!("{}", msg.0);
    }

Here's a gist to my code: gist

Unfortunately, I am out of ideas on how to make the design work. I was thinking about using an enum instead of generics for this, but even in that case, I fail to see how make my design work. The main problem I face is how to store Sender<T> and know which Ts decode function to call.

Any help would be much appreciated.

Aucun commentaire:

Enregistrer un commentaire