usethiserror::Error;#[derive(Error, Debug)]pubenumMyLibError{#[error("Network failed: {0}")]Network(String),#[error("Invalid user ID: {id}")]InvalidUserId{id: u32},#[error("File not found")]NotFound,#[error("IO error: {0}")]Io(#[from]std::io::Error),}
#[from] в Io означает ? превращает std::io::Error в MyLibError::Io(...).
Все функции библиотеки возвращают Result с ошибкой в MyLibError:
pubfnget_user(id: u32)-> Result<String,MyLibError>{ifid==0{returnErr(MyLibError::InvalidUserId{id});}std::fs::read_to_string("config.txt")?;// автоконвертирует тип ошибки
Ok(format!("User {}",id))}
Особенность применения:
Для работы с ошибками в БИБЛИОТЕКАХ (libs)!
В приложениях проще унифицировать тип ошибки, поэтому там применяется anyhow.
Пользователи библиотеки могут проверять по конкретным ошибкам:
useyour_lib::{get_user,MyLibError};matchget_user(0){Ok(name)=>println!("Got {name}"),Err(MyLibError::InvalidUserId{id})=>{println!("You gave ID {id}, but that's invalid!");// обработать конкретно
}Err(MyLibError::NotFound)=>{println!("File missing, creating new one...");// создать файл
}Err(e)=>{println!("Other error: {e}");}}
В случае с anyhow, пользователи получили бы единый тип anyhow::Error и вынуждены были бы парсить строки (плохой код).
Пример применения:
// Библиотека (image_loader.rs)
#[derive(thiserror::Error, Debug)]pubenumImageError{#[error("File too large: {size} bytes")]TooLarge{size: u64},#[error("Unsupported format: {format}")]BadFormat{format: String},#[error("Corrupted data")]Corrupted,}pubfnload_image(path: &str)-> Result<Vec<u8>,ImageError>{// ...
}// Кто-то используем библиотеку:
matchimage_loader::load_image("photo.png"){Ok(data)=>render(data),Err(ImageError::TooLarge{size})=>println!("Your image is {size} bytes, max is 10MB"),Err(ImageError::BadFormat{format})=>println!("Sorry, we don't support {format} files"),Err(ImageError::Corrupted)=>println!("The image is broken"),}