But I feel confused as there's not a way that is seen by the community as a pattern, and if it does, I don't know, and that's what I'm looking for here. Does anyone know what would be the most accepted code for that?
You may be looking for something like this, where the error type is an enum of all possible sub-errors. In this case a match statement is quite natural
enum MyError {
IDontLikeYouException,
YouAreTooShortException,
}
use MyError::*;
fn something_that_may_fail(x: u8) -> Result<(), MyError> {
match x {
0 => Err(IDontLikeYouException),
_ => Err(YouAreTooShortException),
}
}
fn main() {
match something_that_may_fail(1) {
Ok(()) => println!("how did this succeed"),
Err(IDontLikeYouException) => println!("I don't like you"),
Err(YouAreTooShortException) => println!("You are too short"),
}
}
Alternatively if you're dealing with dynamic error types, you can try downcasting to get the underlying type. In this case, the function needs to return something like Result<T, Box<dyn std::error::Error>>. This is a bit closer to Python exceptions, but in Rust the first style is obviously better if you know all your Error types beforehand.
// define IDontLikeYouException and YouAreTooShortException
// as structs implementing std::error::Error
fn something_that_may_fail(x: u8) -> Result<(), Box<dyn std::error::Error>> {
match x {
0 => Err(Box::new(IDontLikeYouException{})),
_ => Err(Box::new(YouAreTooShortException{})),
}
}
fn main() {
match something_that_may_fail(0) {
Ok(()) => println!("how did this succeed"),
Err(e) => {
if let Some(_) = e.downcast_ref::<IDontLikeYouException>() {
println!("I don't like you");
} else if let Some(_) = e.downcast_ref::<YouAreTooShortException>() {
println!("You are too short");
} else {
println!("Unknown error");
}
}
}
}