-1
fn lyrics_more_bottles(song_template: &mut String, number: i32) {
    let mut template_partials = HashMap::new();
    let mut start_num = number.to_string();
    let mut remaining_num = (number - 1).to_string();

    template_partials.insert("start", start_num + " bottles");
    template_partials.insert("repeat", start_num + " bottles");
    template_partials.insert("remaining", remaining_num + " bottles");
    template_partials.insert("message", "Take one down and pass it around");

    resolve_template(song_template, template_partials);
}

I can't manage to convert those concatenated strings to a &str. I tried to put them into parentheses and call .as_str(). No luck on that.

I need to have a HashMap<&str, &str> so having a String is not an option here.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
xetra11
  • 7,671
  • 14
  • 84
  • 159

1 Answers1

2

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 Strings somewhere and fill the map with references into the Strings:

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() {}
Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366