Reputation: 13
I'm trying to get field from my structure in rust
fn check_args(command: i32, args: Vec<String>) -> Vec<Argument> {
let arg_tbl: [ArgsTable; 5] = [
ArgsTable { cc: 0, ac: 1, dv: "4".to_string() },
ArgsTable { cc: 1, ac: 1, dv: "4".to_string() },
ArgsTable { cc: 1, ac: 2, dv: "in.txt".to_string() },
ArgsTable { cc: 4, ac: 3, dv: "1".to_string() },
ArgsTable { cc: 6, ac: 2, dv: "out.txt".to_string() },
];
let mut arguments: Vec<Argument> = Vec::new();
if args.len() == 0 {
for arg in arg_tbl.iter() {
if arg.cc == command {
arguments.push(Argument {
code: arg.ac,
value: arg.dv,
});
}
}
}
}
but get this error
|
151 | value: arg.dv
| ^^^ cannot move out of borrowed content
How can I get the arg.dv
field?
Upvotes: 0
Views: 4249
Reputation: 15232
Although you already have an answer, I will explain the problem and provide a different solution too. I also recommend reading Effectively Using Iterators In Rust.
I'll start with a MCVE, which you can test on the playground too:
struct ArgsTable {
dv: String,
}
fn check_args() -> Vec<ArgsTable> {
let arg_tbl: [ArgsTable; 2] = [
ArgsTable {
dv: "4".to_string(),
},
ArgsTable {
dv: "out.txt".to_string(),
},
];
let mut arguments: Vec<ArgsTable> = Vec::new();
for arg in arg_tbl.iter() {
arguments.push(ArgsTable { dv: arg.dv });
}
arguments
}
fn main() {
check_args();
println!("Hello, world!");
}
This uses arg_tbl.iter()
, which will borrow from arg_tbl
. String
does not implement the Copy
trait, so it can't be copied into arguments
. Because it is borrowed, it can also not be moved. That causes the error message cannot move out of borrowed content
. Because String
does implement Clone
, you can clone it to get a copy. That is why adding a clone()
on line 13 fixes the problem.
It is also possible to fix this using an iterator which does not borrow; into_iter
. But by-value iterators for arrays are not available at the moment. If you use arg_tbl.into_iter()
, the array will dereference into a slice, and you will still iterate by reference! But if you change the array into a Vec
, it will work without having to clone:
let arg_tbl = vec![
ArgsTable {
dv: "4".to_string(),
},
ArgsTable {
dv: "out.txt".to_string(),
},
];
let mut arguments: Vec<ArgsTable> = Vec::new();
for arg in arg_tbl.into_iter() {
arguments.push(ArgsTable { dv: arg.dv });
}
You can now also simplify the for loop like this:
for arg in arg_tbl {
Upvotes: 7