Let's say I have the following struct
pub struct ReplacementSettings<'a> {
/// A list of all replacement values
pub replacements: HashMap<String, Vec<String>>,
/// An internal list of value which are going to be replaces without user input.
direct_replacements: HashMap<&'a str, Vec<&'a str>>,
/// An internal list of values that are going to be presented to the user
search_list: HashSet<&'a str>,
}
The replacements
HashMap is filled when the struct is created and can be changed by the user. The direct_replacements
and search_list
fields are generated by a separate function from the replacements
field and cannot be changed by the user directly.
The fill routine roughly goes like this:
pub fn new(path: PathBuf) -> Result<ReplacementSettings<'a>, SettingsError> {
let mut file = File::open(&path)?;
let mut buffer = String::new();
file.read_to_string(&mut buffer)?;
let mut config: ReplacementSettings = toml::from_str(&buffer)?;
for (key, terms) in &config.replacements {
if value.is_empty() {
config.search_list.insert(key);
} else {
for term in terms {
config.direct_replacements.insert(term, key);
}
}
}
Ok(config)
}
But when I try to compile I get two errors:
a) [E0505]: cannot move out of config
because it is borrowed
b) [E0515]: cannot return value referencing local data config.replacements
and I'm asking myself, if this is even possible. This very much looks like a self-referencing struct, which as far as I know is very hard to pull off and a bit discouraged.
Now I could clone each string and store them in the two fields when they are filled, but the replacements
HashMap contains thousands of Strings and there are possibly hundreds of ReplacementSettings
this would mean a lot of string allocations. Since direct_replacements
and search_list
are only ever read by the user I don't see the point in that.
Am I missing something obvious here?