I import this to other crate wich has mocked service using it
#[derive(Default, Debug)]
pub struct ProductService<'a> {
products: Vec<Product<'a>>
}
impl ProductService<'_> {
pub fn new() -> Self {
let products = file_helper();
for product in products.iter() {
println!("{}", product.id());
}
ProductService {
products
}
}
pub fn get_products(&self) -> &Vec<Product> {
&self.products
}
}
fn file_helper() -> Vec<Product<'static>> {
let data = std::fs::read_to_string("./products.json").expect("Unable to read file");
let json: Vec<Product> = serde_json::from_str(&data).expect("error parsing");
json
}
The problem is in fn file_helper() which try to deserialize json data. This json file I create earlier by manually creating Products to vector and serialize it with writting to file. Now this file I'm trying to deserialize.
When I try to build this I'm gettint error:
error[E0515]: cannot return value referencing local variable `data`
--> src/handlers/../services/productservice.rs:65:5
|
63 | let json: Vec<Product> = serde_json::from_str(&data).expect("error parsing");
| ----- `data` is borrowed here
64 |
65 | json
| ^^^^ returns a value referencing data owned by the current function
This function I've moved from new() because I had the same probem but moving outside didnt help
When I try to create manulaly vector of Products it works, byt from deserialize does't.
How to solve this problem? Should I change &a' str in my Product struct to String? or somtething else?
Thanks for help in advance.
Inline the helper will work. But in the general case, unless you benchmarked and found out creating Strings is the bottleneck, you should just use String.
This is almost certainly the correct solution for you. &’a str always refers to data that is owned elsewhere; in the case of your deserialization code, that’s the variable data which contains the unparsed JSON.
In order to keep using &’a str inside the struct Product, you’ll need to store the read file somewhere that lives as long as ’a. Inlining file_helper as @zirconium-n mentions is one way to do this. Another is to give file_helper access to a buffer that will live long enough:
Thank you guys for claryfication. This is my trainings because I had long pause with rust and I'm starting learn it again.
I'm think that better for me wiil be to store String struct in Product.
Thanks again
Here it is better to take a String so you can avoid the clone. That way, the string does not have to be cloned when that isn't necessary, and when a clone is necessary, the caller can do so.
Here you should take a &[...] as argument instead of a Vec. This way the caller can call the method without having to create a Vec just for that purpose.
Here you should return a &[String]. This is like the case with &String.