Как выбросить ошибку при ложном значении?
Есть некий код читающий бинарный файл, необходимо при попытке чтения неизвестного файла бросить исключение, или просто сделать вылет с ошибкой, т.к. я еще не совсем понимаю синтаксис языка прошу подсказать как это сделать:
impl Header {
fn read(file: &mut std::fs::File) -> Header {
file.rewind();
let sig: String;
let ver: u32;
let web: String;
let min: String;
let mut file_reader = BufReader::new(file);
let mut buffer = Vec::new();
file_reader.read_until(0u8, &mut buffer);
let good = {
let valid = String::from("UnityFS");
let res = valid == String::from_utf8(buffer).unwrap();
if res {
sig = valid;
}
res
};
// Нужно здесь выбросить ошибку
assert_eq!(good, false, "Unknown file type.");
...
Header {
signature: sig,
version: ver,
web_version: web,
min_version: min
}
}
}
Ответы (1 шт):
Общепринятый подход к обработке ошибок в Rust — воспользоваться стандартным типом Result:
impl Header {
fn read(file: &mut std::fs::File) -> Result<Self, HeaderReadError> {
// ...
}
}
Для определения типа данных ошибки есть хорошие рекомендации по API. Если ошибку в данном случае предполагается обрабатывать во внутреннем коде, можно воспользоваться простым типом Error, предлагаемым anyhow. Если это библиотека или большое приложение, стоит определить тип более детально и эргономично, например, воспользовавшись макросом derive из thiserror:
#[derive(thiserror::Error, Debug)]
enum HeaderReadError {
#[error("failed to read header from file")]
Io(#[from] std::io::Error),
#[error("invalid UTF-8 in file content")]
Utf8Decode(#[from] std::string::FromUtf8Error),
#[error("unknown file type")]
UnknownFileType,
}
Стоит заметить, что эта структура не содержит никаких строк с описанием ошибки: они производятся на лету в сгенерированной процедурным макросом реализации Display.
Это определение также позволит вам удобно обработать все другие ошибочные ситуации, которые могут возникать в примере, но в оригинальном коде игнорируются или приводят к панике. Сгенерированные макросом преобразования From позволяют воспользоваться оператором ?:
const HEADER_SIGNATURE: &str = "UnityFS";
impl Header {
fn read(file: &mut std::fs::File) -> Result<Self, HeaderReadError> {
file.rewind()?;
let mut file_reader = BufReader::new(file);
let mut buffer = Vec::new();
file_reader.read_until(0u8, &mut buffer)?;
let signature = String::from_utf8(buffer)?;
// Нужно здесь выбросить ошибку
if signature != HEADER_SIGNATURE {
return Err(FileReadError::UnknownFileType);
}
Ok(Header {
signature,
// ...
})
}
}