Мне нужно прочитать вектор, например, целые числа из потока, обычно из стандартного ввода, но иногда и из файла. Ввод всегда меньше мегабайта и иногда разделяется запятыми, а иногда и новой строкой.
Я вызываю код непосредственно из своей основной функции, поэтому меня больше интересует возвращение ошибки, удобочитаемой человеком, а не чего-то, что может быть обнаружено и восстановлено программно, поэтому я использую String
как тип ошибки.
pub fn parse_vector<T: BufRead, S: FromStr>(buf: T, sep: u8) -> Result<Vec<S>, String> {
buf.split(sep)
.enumerate()
.filter_map(|(i, entry)| {
let entry_nr = i + 1;
let entry = match entry.map(String::from_utf8) {
Err(e) => return Err(format!("Cannot read entry {}, {}.", entry_nr, e)).into(),
Ok(Err(e)) => return Err(format!("Cannot read entry {}, {}.", entry_nr, e)).into(),
Ok(Ok(v)) => v,
};
let trimmed = entry.trim();
if trimmed.is_empty() {
None
} else {
Some(
trimmed
.parse::<S>()
.map_err(|_| format!("Cannot parse entry {}: '{}'", entry_nr, entry)),
)
}
})
.collect()
}
Приведенный выше код работает, насколько я могу судить, но мне интересно, есть ли лучший способ справиться с беспорядком в match
выражение. Функции from_utf8
и split
возвращают разные типы ошибок, но оба реализуют Display
так что, может быть, есть какой-нибудь элегантный способ устранить там дублирование кода, о котором я не знаю (я новичок в ржавчине, пришедший из С ++).
- Как я могу сделать этот код более читабельным?
- Считается плохой практикой возвращаться
String
как тип ошибки?