I am trying to do some refactoring from my codebase?
I have code like this:
fn foo() -> Result<Value, String>
let query_result: QueryResult<...> = <query to the database>
let value: Value = if query_result.is_err() {
let err_msg = query_result.err().unwrap().to_string();
return Err(format!("Error in Foo: {err_msg}"));
} else {
query_result.unwrap()
};
value
This code is essentially the pattern I follow to add error handling. I am trying to make a function to do this, but I don't want to panic out of the function and instead return the value. I assume this would be very difficult as Rust doesn't support returning multiple types. I could make an enum, but I would have to have a way to tell the function calling the unwrap function to return Err(format!("Error in Foo: {err_msg}")); . Thank you in advance for any help any of yall can provide.
I don’t quite follow what you’re asking for, but you can simplify the code you posted like this:
fn foo() -> Result<Value, String> {
let query_result: QueryResult<...> = <query to the database>;
query_result.map_err(|e| format!("Error in Foo: {}", e.to_string()));
}
You also might find the ? operator useful, as it’s designed to help with error propagation.
If you want to pull this out into a separate function, you can do something like this:
fn format_err<T,E:Display>(result: Result<T,E>, context: &str)->Result<T, String> {
result.map_err(|e| format!("Error in {context}: {e}"))
}
fn foo() -> Result<Value, String> {
let query_result: QueryResult<...> = <query to the database>;
let value: Value = format_err(query_result, "Foo")?;
// Do something with `value`
Ok(value)
}
Another way analogous to a separate function is to implement
impl From<(Tuple, Of, Context)> for CustomErrorType { .. }
And then you can do things like
fn foo() -> Result<Value, CustomErrorType> {
let value = query_result.map_err(|e| ("foo", e))?;
}
Larger example here. It is a lot of boilerplate. It's also not applicable if your error type is just String, since you can't write the From implementation in that case.
No, res? on a res: Result is roughly equivalent to
match res {
Ok(value) => value,
Err(e) => return Err(e.into()),
}