I have a struct that looks something like this:
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Settings {
editor: String,
poll_rate: usize,
pb_len: usize,
pb_parts: String,
pb_format: String,
frame_parts: String,
..
}
that has a method like this:
impl Settings {
pub fn read() -> Self {
path_to::settings().fs_read_to_string().to_settings()
}
..
}
path_to mod contains functions that generate paths to assets, where fn settings() -> String
the rest of the chain is implemented through traits on String:
trait FsToString {
fn fs_read_to_string(&self) -> String;
}
impl FsToString for String {
fn fs_read_to_string(&self) -> String {
std::fs::read_to_string(self).unwrap_or_default()
}
}
...and:
trait ToSettings {
fn to_settings(&self) -> Settings;
}
impl ToSettings for String {
fn to_settings(&self) -> Settings {
match serde_yaml::from_str::<Settings>(self) {
Ok(settings) => settings,
Err(err) => {
println!("{err}");
Settings::default()
}
}
}
}
This is, obviously, not the only way to achieve what I'm after, and not even the one I like...
but IT WORKS - that's the main thing.
So, as an experiment, I figured to try and generalize it:
trait ToSettings <'de, T> {
fn to_settings(&self) -> T
where
T: Deserialize<'de> + Default;
}
impl <'de, T> ToSettings <'de, T> for String
where
T: Deserialize<'de> + Default
{
fn to_settings(&self) -> T {
match serde_yaml::from_str::<T>(self) {
Ok(settings) => settings,
Err(err) => {
println!("{err}");
T::default()
}
}
}
}
This, however, DOESN'T WORK:
error: lifetime may not live long enough
--> src\structs\settings_re.rs:44:15
|
39 | impl <'de, T> ToSettings <'de, T> for String
| --- lifetime `'de` defined here
...
43 | fn to_settings(&self) -> T {
| - let's call the lifetime of this reference `'1`
44 | match serde_yaml::from_str::<T>(self) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'de`
From everything above I infer that if the compiler knows that the struct you're trying to deserialize has only owned types in it, it has no problem with "letting go" of the reference, while if fields are obscured by generics you get the ever-dreaded lifetime problem.
I would like to know if there's a way to indicate the fact that there are indeed "only owned things here" as some sort of a trait bound(?) Maybe, indicate something on Self type (although I fail to see how this would help)?
More generally I want to know why the explicit implementation works and the "fuzzy" one doesn't.