If you need to return the &str
from the function, you are out of luck, see Return local String as a slice (&str).
If you just need to put the slices into a HashMap
and pass it further down, you need to store the String
s somewhere and fill the map with references into the String
s:
use std::collections::HashMap;
fn resolve_template(_: &mut String, _: HashMap<&str, &str>) {}
fn lyrics_more_bottles(song_template: &mut String, number: i32) {
let mut start_num = number.to_string();
let mut remaining_num = (number - 1).to_string();
let start = start_num.clone() + " bottles";
let repeat = start_num + " bottles";
let remaining = remaining_num + " bottles";
let mut template_partials = HashMap::new();
template_partials.insert("start", &*start);
template_partials.insert("repeat", &*repeat);
template_partials.insert("remaining", &*remaining);
template_partials.insert("message", "Take one down and pass it around");
resolve_template(song_template, template_partials);
}
fn main() {}
We use &*
to Deref
the String
to a str
and then take another reference to end up at a &str
.
Note that the let mut template_partials
line has to be moved after the strings are created, otherwise when the strings are dropped, the map might contain references to invalid memory. Additionally, the start_num
needs to be cloned as it's used twice.
Personally, I'd just use format!
and use the same string twice instead of cloning and modifying it twice:
use std::collections::HashMap;
fn resolve_template(_: &mut String, _: HashMap<&str, &str>) {}
fn lyrics_more_bottles(song_template: &mut String, number: i32) {
let start_and_repeat = format!("{} bottles", number);
let remaining = format!("{} bottles", number - 1);
let mut template_partials = HashMap::new();
template_partials.insert("start", &*start_and_repeat);
template_partials.insert("repeat", &*start_and_repeat);
template_partials.insert("remaining", &*remaining);
template_partials.insert("message", "Take one down and pass it around");
resolve_template(song_template, template_partials);
}
fn main() {}