map_err transforms the error value in a Result while leaving an Ok result unchanged. It calls a supplied function only for Err, then wraps that function's return value in the new Err variant. section 2.5.5
Converting validation errors
Suppose validate_lowercase and validate_unique both return Result<(), ()>, while validate_username must return Result<(), UsernameError>. Applying map_err converts each unit error into the matching UsernameError variant; ? then returns the converted error early. The Ok path continues without calling the conversion function. section 2.5.5
fn map_err<T, E1, E2>(
r: Result<T, E1>,
transform: fn(E1) -> E2,
) -> Result<T, E2> {
match r {
Ok(x) => Ok(x),
Err(e) => Err(transform(e)),
}
}
The equivalent match implementation makes the operation explicit: preserve Ok(x), transform Err(e), and wrap the transformed value in Err. section 2.5.5
fn validate_username(username: &str) -> Result<(), UsernameError>
{
validate_lowercase(username).map_err(lowercase_err)?;
validate_unique(username).map_err(unique_err)?;
Ok(())
}
fn lowercase_err(x: ()) -> UsernameError {
UsernameError::NotLowercase
}
fn unique_err(x: ()) -> UsernameError {
UsernameError::NotUnique
}
The validation example applies named conversion functions before propagating errors with ?. Closures provide a shorter equivalent form. section 2.5.5
