Rust, mapping between result types

I encountered a problem where my function uses,
Result<Value, String>, but I also use Hugging Face Candle and std::fs::read, both of which have their own result types.
For example, std::fs::read returns io::Result<Vec<u8>>.
This means you can’t simply use the standard ? syntax to return the result.

There are two ways to handle this:

  1. The long way is to use a match statement:
let content = match std::fs::read(config_filename) {
    Ok(content) => content,
    Err(e) => return Err(format!("Error reading config file: {e}"))

2. Or, you can use map_err, a method on the Result object:

let content = match std::fs::read(config_filename).map_err(|e| e.to_string())?

I don’t think one approach is necessarily better than the other, but one is certainly shorter. This method really shines when you have multiple such operations in one intent:

let config: LlamaConfig = serde_json::from_slice(
    &std::fs::read(config_filename).map_err(|e| e.to_string())?
).map_err(|e| e.to_string())?;

You could also write this as a single line of code, but there’s no need to punish yourself.

Thus, map_err provides a clearer way to map between result types.