0
votes

I need to create a Vec like this code :

use serde::{Serialize, Deserialize};
trait TPlugin<'a, Config> where Config : Serialize + Deserialize<'a> {}

#[derive(Serialize, Deserialize)]
struct MyConfig {}

struct MyPlugin1 {
  conf: MyConfig,
}
impl TPlugin<MyConfig> for MyPlugin1 {}
impl MyPlugin1 {
  pub fn new() -> MyConfig1 {
    MyConfig1{}
  }
}

fn main() {
  let my_vec: Vec<Box<dyn TPlugin<????>>> = Vec::new();
  my_vec.push(MyConfig1::new());
  my_vec.push(MyConfig2::new());
}

What is the code that I must add instead of "????"? I've tried Box<dyn Serialize + Deserialize<'a>> but rust tells me "the trait serde::Serialize cannot be made into an object".

I'm newbie on rust, so generics are obscure for me, like lifetimes. I'm from Java/Typescript. In Java/Typescript I write:

let myVec: Vec<TPlugin<?>>;

Regards.

1

1 Answers

0
votes

First to focus on the core problem: To have a Vec of heterogenous objects, you must use dynamic dispatch, for example the Box<dyn ...>, which you already used successfully. But then inside you need another dynamic dispatch and this one is not possible. The Box<dyn ...> will end up being a "fat pointer" - one pointer pointing to the data, other pointer pointing to a virtual table for that type. Virtual table is generated by the compiler and contains pointer to implementation of every method the type has. And here comes the problem, look at the Serialize trait:

pub trait Serialize {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer;
}

It has one method serialize, but this method is generic over Serializer. So really there is not one method, but "infinite" amount of methods, one for each possible Serializer. The compiler is not able to make virtual table for that, so Serializer can not be made into an (trait) object.

I would suggest you to define your own trait that describes what you want to do with Config and is object safe. Perhaps methods for saving and loading with a specific Serializer, toml for example?