Как выбросить ошибку при ложном значении?

Есть некий код читающий бинарный файл, необходимо при попытке чтения неизвестного файла бросить исключение, или просто сделать вылет с ошибкой, т.к. я еще не совсем понимаю синтаксис языка прошу подсказать как это сделать:

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 шт):

Автор решения: mzabaluev

Общепринятый подход к обработке ошибок в 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,
            // ...
        })
    }
}
→ Ссылка