Rust doesn’t have exceptions. Instead, functions that can return result type like following code.
fn get_weather(location: LatLng) -> Result<WeatherReport, io::Error>
Defining a public type std::io::Result<T>
is an an alias for Result<T, E>.
pub type Result<T> = std::result::Result<T, Error>;
After that, you can define Result
to return like this.
fn remove_file(path: &Path) -> Result<()>
?
operator propagate errors up to the call stack. The behavior of ?
depends on whether this function returns a success result or an
error result:
fn move_all(src: &Path, dst: &Path) -> io::Result<()> {
for entry_result in src.read_dir()? {
// opening dir could fail
let entry = entry_result?; // reading dir could fail
let dst_file = dst.join(entry.file_name());
fs::rename(entry.path(), dst_file)?; // renaming could fail
}
Ok(()) // phew!
}
There are two ways to handle multiple error type.
1. Implement conversion: ?
operator does automatic conversion using a standard method.
pub enum MyError {
DatabaseError(Box<dyn Debug>),
ZeroDivisionError,
InternalServerError,
}
impl From<MyError> for std::io::Error{
fn from(value:MyError) -> Self {
match value {
MyError::DatabaseError(_) => todo!(),
MyError::ZeroDivisionError => todo!(),
MyError::InternalServerError => todo!(),
}
todo!()
}
}
Box<dyn std::error::Error + Send + Sync + 'static>
.type GenericError = Box<dyn std::error::Error + Send + Sync + 'static>;
type GenericResult<T> = Result<T, GenericError>;