I've written some code based on reqwest and Tiberius that consumes data from a web API, deserializes the JSON response into structs, does some work and then writes the results to SQL.
My datasets are encapsulated in the structs and all the datasets implement the trait ApiCaller which uses an associated type via
impl ApiCaller for Vec mydataset
I really wanted to pass the objects to an mpsc channel via a message containing dyn ApiCaller and receive a deserialized vector back. Mpsc is useful because i can add further requests to the channel during processing.
I've just discovered that dynamic dispatch and associated types in traits are incompatible so i can't use the mpsc channel in the way that i planned.
I'm beginning to despair because i feel like calling an API and handling the responses should be simple but rust is just ... not.
Is there an idiomatic rust way i should approach this? I've tried to refactor using enums but I'm still stuck because the deserialized output of my Api call still needs to be of type dyn ApiCaller
Thanks, I have read these links but i think I'm reaching saturation point of new information.
My primary obstacle is that the associated types are generic. I think I'm going to have to rethink and refactor but I'm not sure of the direction to go.
I want to process and add to a queue of dyn trait, but i can't use dyn trait because I've got generic associated types in my traits.
In that case it would be best to use an enum instead of trait objects. This works quite well, as long as all enum variants are known at compile time of course. Another advantage (perhaps minor for you) of an enum is that you don't need to box it because it is fixed size.
EDIT:
Another approach is to have a queue of Box<dyn Any> and then downcast to a specific type when you receive the deserialized object from the channel. However, you have to know the explicit type for downcasting. If the code receiving from the channel knows this type, you're fine. If it doesn't, then you need to send some sort of type identifier in the response message, and in that case it may be simpler to just use an enum instead of Box<dyn Any>.
Here is a playground showing how to use downcasting, along with limited trait objects for traits with associated types.
Thank you for your help, I came back to this after a busy few weeks at work and refactored to use enums which now work perfectly. The added overall code has become easier to read now too.