I have read those two similar questions here and here. But still can't figure out how to achieve what I want: initializing a String field in a struct with a String that belongs to a HashMap in the same structure. Here is my initial code:
use std::collections::HashMap;
struct S<'a> {
a: HashMap<String,Vec<String>>,
b: &'a String,
}
impl <'a> S<'a> {
fn new() -> S<'a> {
let mut v:Vec<String> = Vec::new();
v.push("a".to_string());
v.push("b".to_string());
let mut h = HashMap::new();
h.insert("toto".to_string(),v);
let b = &h.get("toto").unwrap()[0];
S {
a: h, // error[E0505]: cannot move out of `h` because it is borrowed
b: b // error[E0515]: cannot return value referencing local variable `h`
}
}
}
fn main() {
let mut s = S::new();
println!("s.b = {}", s.b);
}
I would like b to be initilaized with a String value that belong to the HashMap a. Since the above did not work, I tried to initialize b with an empty String, and immediatly change b's value after creating s:
use std::collections::HashMap;
struct S {
a: HashMap<String,Vec<String>>,
b: String,
}
impl S {
fn new() -> S {
let mut v:Vec<String> = Vec::new();
v.push("a".to_string());
v.push("b".to_string());
let mut h = HashMap::new();
h.insert("toto".to_string(),v);
let b = "".to_string();
S {
a: h,
b: b
}
}
}
fn main() {
let mut s = S::new();
s.b = s.a.get("toto").unwrap()[0]; //error[E0507]: cannot move out of index of `Vec<String>`
println!("s.b = {}", s.b);
}
Since I cannot copy the value into s.b:
error[E0507]: cannot move out of index of `Vec<String>`
--> src/main.rs:24:15
|
24 | s.b = s.a.get("toto").unwrap()[0]; //error[E0507]: cannot move out of index of `Vec<String>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `String`, which does not implement the `Copy` trait
For more information about this error, try `rustc --explain E0507`.
I thought that a reference could work:
use std::collections::HashMap;
struct S<'a> {
a: HashMap<String,Vec<String>>,
b: &'a String,
}
impl <'a> S<'a> {
fn new() -> S<'a> {
let mut v:Vec<String> = Vec::new();
v.push("a".to_string());
v.push("b".to_string());
let mut h = HashMap::new();
h.insert("toto".to_string(),v);
let b = &"".to_string();
S {
a: h,
b: b // error[E0515]: cannot return value referencing temporary value
}
}
}
fn main() {
let mut s = S::new();
s.b = &s.a.get("toto").unwrap()[0];
println!("s.b = {}", s.b);
}
But of course, I run into the same issue of referencing a value that does not have a lifetime longer than the function. No clue how/if I can tell the compiler that my empty String should live as long as S.
There might be an obvious solution, but if so, I can't see it :-(