I take into consideration the answer of @cdhowie and try to make the example work entirely.
To do so, we have to ensure the lifetime of the incoming string (str_json
) is compatible with the lifetime of Deserialize<'a>
.
With a String
parameter, it is not the case: it will disappear when the function ends.
Then, we need a &str
and explicitly associate its lifetime with the one of Deserialize<'a>
.
This page explains quite well why the lifetime on Deserialize<'a>
is important: it enables zero-copy extractions (when suitable).
In order to illustrate this, the example below first deals with a struct which owns its data (a String
) and then a second struct which references its data (a &str
).
According to the same page, DeserializedOwned
is to be considered when we cannot guaranty that the incoming string to be parsed will live longer than the extracted data.
In this case, we can get back to the situation where the parameter is a String
.
use serde::{de::DeserializeOwned, Deserialize};
#[derive(Debug)]
struct S1<T> {
pub data: T,
}
impl<'a, T> S1<T>
where
T: Deserialize<'a>,
{
fn update_from_str(
&mut self,
str_json: &'a str,
) {
self.data = serde_json::from_str(str_json).unwrap();
}
}
impl<T> S1<T>
where
T: DeserializeOwned,
{
fn update_from_string(
&mut self,
str_json: String,
) {
self.data = serde_json::from_str(&str_json).unwrap();
}
}
fn main() {
let mut owned = S1 {
data: "one".to_owned(),
};
println!("owned before {:?}", owned);
owned.update_from_str(" \"two\" ");
println!("owned after {:?}", owned);
//
let mut referenced = S1 { data: "three" };
println!("referenced before {:?}", referenced);
referenced.update_from_str(" \"four\" ");
println!("referenced after {:?}", referenced);
//
let mut owned_and_string = S1 {
data: "five".to_owned(),
};
println!("owned_and_string before {:?}", owned_and_string);
owned_and_string.update_from_string(" \"six\" ".to_owned());
println!("owned_and_string after {:?}", owned_and_string);
}
/*
owned before S1 { data: "one" }
owned after S1 { data: "two" }
referenced before S1 { data: "three" }
referenced after S1 { data: "four" }
owned_and_string before S1 { data: "five" }
owned_and_string after S1 { data: "six" }
*/