0

I need to call a generic method in the content of a String which is coming from a FFI caller, not from a static &str in the code:

match endpoint.as_ref() {
    "documents" => get_objs_as_json::<Document, JsonDocument>(db_url, sql),
    "theme_links" => get_objs_as_json::<ThemeLink, JsonThemeLink>(db_url, sql),
    "dressing_links" => get_objs_as_json::<DressingLink, JsonDressingLink>(db_url, sql),
    "dressing_configurations" => {
        get_objs_as_json::<DressingConfiguration, JsonDressingConfiguration>(db_url, sql)
    }
    &_ => Err(BackendError::InvalidArgument(endpoint)),
}

It's working, but really ugly, and I need to do this for each generic methods I have…

I tried to make an hashmap like endpoint => (InputStruct, OutputStruct) but I can't store and use the types like that.

Perhaps I can do that with a macro, but I don't know how to convert the string parameter into types in the macro.

EDIT Ok, trying to reformulate. I have a generic method who get data in my database from on struct type, then convert it to some other struct. But my caller doesn't know the name of the structs, so I need a wrapper to convert an arbitrary string to a couple of types. The idea here is to replace (as in a C macro, even if I know that Rust macros are different)

get_and_convert("documents", params)

by

get_and_convert<Document, JsonDocument>(params)

That because the "documents" parameter come from FFI, the caller don't know the rust internal and can't call the generic method.

as in :

pub struct Document {
    pub a: i32,
}

pub struct JsonDocument {
    pub a: i32,
}

impl JsonDocument {
    pub fn to_json(&self) -> String {
        // …
    }
}

impl From<Document> for JsonDocument {
    fn from(input: Input) -> Self {
        Output {
            a: input.a
        }
    }
}

pub fn get_and_convert<I, O>(db_params: String) -> String {
    let input = get_data(db_params);
    let output = input.into();
    output.to_json()
}

So I tried something like that (I'm new to macros so the code is very wrong, read it more like a pseudo-code) :

macro_rules! get_types {
    ("documents") => {
        (Document, JsonDocument)
    };
    ("themes") => {
        (Theme, JsonTheme)
    };
}

macro_rules! get_objs {
    ($x:expr, $y:expr, $params:expr) => {
        get_and_convert::<$x, $y>($params)
    };
}

used like :

pub fn testmacro(args: String) {
    let (input_type, output_type) = get_types!("documents");
    let result = get_objs!(input_type, output_type, args);
}
Ishtar
  • 19
  • 1
  • 3
  • 4
    What is `get_objs_as_json`? Writing a [mcve] will make it easier for someone to answer your question. – Peter Hall Mar 01 '19 at 15:18
  • You can store hastable of traits like [here](https://stackoverflow.com/questions/49711479/how-can-i-create-hashable-trait-objects-trait-objects-with-generic-method-para) if that is what you need – Akiner Alkan Mar 01 '19 at 15:33

0 Answers0