I want to get something similar following code to return a struct which is deserialized from an input file. The goal is to hide the deserialization implementation from the api client.
let a_struct = a_module::from_file<AStruct>("/configuation/file.path")?
The following code demonstrates the problem that I am having.
trait MyTrait {
fn do_something(&self) -> String;
}
#[derive(serde::Deserialize)]
struct MyStruct<'a> {
field: &'a str,
}
impl MyTrait for MyStruct<'_> {
fn do_something(&self) -> String {
self.field.to_owned()
}
}
fn from_str<S, T>(s: S) -> T
where S: AsRef<str>,
T: MyTrait + serde::de::DeserializeOwned
{
serde_yaml::from_str::<T>(s.as_ref()).unwrap()
}
trait MyTrait {
fn do_something(&self) -> String;
}
#[derive(serde::Deserialize)]
struct MyStruct<'a> {
field: &'a str,
}
impl MyTrait for MyStruct<'_> {
fn do_something(&self) -> String {
self.field.to_owned()
}
}
fn from_str<S, T>(s: S) -> T
where S: AsRef<str>,
T: MyTrait + serde::de::DeserializeOwned
{
serde_yaml::from_str::<T>(s.as_ref()).unwrap()
}
fn main() {
let a = from_str::<MyStruct>("a: A String");
//let a = from_str::<_, MyStruct>("a: A String");
dbg!(a.do_something());
}
When I try to use from_str::<MyStruct>("a: A String");
i get:
error[E0107]: this function takes 2 generic arguments but 1 generic argument was supplied
--> src/main.rs:24:13
|
24 | let a = from_str::<MyStruct>("a: A String");
| ^^^^^^^^ -------- supplied 1 generic argument
| |
| expected 2 generic arguments
|
note: function defined here, with 2 generic parameters: `S`, `T`
--> src/main.rs:16:4
|
16 | fn from_str<S, T>(s: S) -> T
| ^^^^^^^^ - -
help: add missing generic argument
|
24 | let a = from_str::<MyStruct, T>("a: A String");
| +++
When I try to use from_str::<_, MyStruct>("a: A String");
error: implementation of `Deserialize` is not general enough
--> src/main.rs:25:13
|
25 | let a = from_str::<_, MyStruct>("a: A String");
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
|
= note: `MyStruct<'_>` must implement `Deserialize<'0>`, for any lifetime `'0`...
= note: ...but `MyStruct<'_>` actually implements `Deserialize<'1>`, for some specific lifetime `'1`
I've don't understand why I need to pass the _ generic parameter in the second attempt but the error looks like it is getting closer to the root cause. I have tried all sorts of changes to the lifetimes and trait bounds of the function to no avail. If i read the file, deserialize it, and use the struct all in the main function it works perfectly...
How can I do this?