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);
}