I am parsing a toml config file and retrieve it's content into some structs, using serde
and toml
.
So, a config structure could be defined like:
#[derive(Deserialize, Debug)]
pub struct Config<'a> {
#[serde(borrow)]
pub server: Inner<'a>
}
and another related:
#[derive(Deserialize, Debug)]
pub struct Inner<'a> {
pub iprop1: &'a str,
pub iprop2: &'a str,
}
This is the pub interface exposed for loading the config:
pub fn load() -> Config<'static> {
let config_file: String = fs::read_to_string(CONFIG_FILE_IDENTIFIER)
.expect("Error opening or reading the configuration file");
toml::from_str(config_file.as_str())
.expect("Error generating the configuration")
}
So, the issue it's clear. I can return data owned by the load()
function.
I could change all the &str
refereneces to String
, because I am not able to fully comprehend how to properly play with references in Rust, but I would like to know, if there's another way to validate those references with lifetimes in Rust, so my structs can start to hold references instead owned values.
References refer to data owned elsewhere. For this to work, the data being referred to must live at least as long as the reference, otherwise you have a reference to data that no longer exists.
In your load()
function, the return type declares that Config
will borrow data that is 'static
. This is a special lifetime that refers to data that is valid for the entire lifetime of the program.
However, toml::from_str()
here borrows from config_file
, which does not live for the entire lifetime of the program. It lives only until load()
returns. You are attempting to return a reference to data owned by a function local, which is impossible, because the data will be destroyed before the returned reference can ever be used.
If there is nowhere else for config_file
to live, the data should indeed be owned by the Config
structure. The way you express that is by using String
instead of &str
within that structure.