问题
I'm trying to parse a simple config text file, which contains one three-word entry per line, laid out as follows:
ITEM name value
ITEM name value
//etc.
I've reproduced the function which does the parsing (and the subsequent compilation error) here (and on the Rust Playpen):
pub fn parse(path: &Path) -> config_struct {
let file = File::open(&path).unwrap();
let reader = BufReader::new(&file);
let line_iterator = reader.lines();
let mut connection_map = HashMap::new();
let mut target_map = HashMap::new();
for line in line_iterator {
let line_slice = line.unwrap();
let word_vector: Vec<&str> = line_slice.split_whitespace().collect();
if word_vector.len() != 3 { continue; }
match word_vector[0] {
"CONNECTION" => connection_map.insert(word_vector[1], word_vector[2]),
"TARGET" => target_map.insert(word_vector[1], word_vector[2]),
_ => continue,
}
}
config_struct { connections: connection_map, targets: target_map }
}
pub struct config_struct<'a> {
// <name, value>
connections: HashMap<&'a str, &'a str>,
// <name, value>
targets: HashMap<&'a str, &'a str>,
}
src/parse_conf_file.rs:23:3: 27:4 error: mismatched types:
expected `()`,
found `core::option::Option<&str>`
(expected (),
found enum `core::option::Option`) [E0308]
src/parse_conf_file.rs:23 match word_vector[0] {
src/parse_conf_file.rs:24 "CONNECTION" => connection_map.insert(word_vector[1], word_vector[2]),
src/parse_conf_file.rs:25 "TARGET" => target_map.insert(word_vector[1], word_vector[2]),
src/parse_conf_file.rs:26 _ => continue,
src/parse_conf_file.rs:27 }
In essence, I seem to have created a match
statement that expects an empty tuple, and also finds the contents of a Vec<&str>
to be wrapped in an Option
!
NB. This post originally contained two questions (that I'd believed were one error manifesting itself differently), but as-per advice in the comments I've split it into two separate posts. The latter post is here.
回答1:
Your original problem is just that you have a non-()
expression at the end of your loop body. Your match
expression has type Option<&str>
(because that is the return type of HashMap::insert
), not type ()
. This problem is solved by simply putting a semicolon after the match expression:
match word_vector[0] {
"CONNECTION" => connection_map.insert(word_vector[1], word_vector[2]),
"TARGET" => target_map.insert(word_vector[1], word_vector[2]),
_ => continue,
};
For the latter, isn't word_vector populated with owned objects that don't point to line_slice?
No, which is precisely the issue. word_vector
contains elements of type &str
, i.e. borrowed strings. These point into line_slice
, which only lives until the end of the current loop iteration. You probably want to convert them to String
s (using String::from
) before inserting them into the map.
来源:https://stackoverflow.com/questions/31620888/textfile-parsing-function-fails-to-compile-owing-to-type-mismatch-error