How to use dynamic dispatch in Rust for trait with generics?

I'm using a trait called RtspClient so I can create different Stream objects with different rtsp clients:

pub trait RtspClient {
    fn url(&self) -> Option<String>;
    fn username(&self) -> Option<String>;
    fn password(&self) -> Option<String>;
    fn connect(&self) -> Result<(), RtspClientError>;
    fn disconnect(&self) -> Result<(), RtspClientError>;
    fn set_on_produce<F: Fn(EncodedPacket)>(&self, f: F);
}

then I'm using it like this:

struct Stream {
    pub rtsp_client: Arc<Mutex<dyn RtspClient>>,
}

but I get the error that RtspClient cannot be used as an object because set_on_produce has generic types.

How can I use dynamic dispatch for rtsp_client and still be able to set closure callbacks with set_on_produce?

You'll have to replace generic methods with ones that only involve concrete types. E.g.:

fn set_on_produce(&self, f: Box<dyn Fn(EncodedPacket)>);

By the way, in generic callbacks, you should really allow FnMut unless you have a requirement of restricting to Fn, so my final advice would be to write

fn set_on_produce(&self, f: Box<dyn FnMut(EncodedPacket)>);

(Oh, and also, why doesn't a setter method like set_on_produce take &mut self?)

2 Likes