0

I have a rust program that has multiple nested match statements as shown below.

match client.get(url).send() {
    Ok(mut res) => {
        match res.read_to_string(&mut s) {
            Ok(m) => {
                match get_auth(m) {
                  Ok(k) => k,
                  Err(_) => return  Err(“a”);
               }
            },
            Err(_) => {
                return Err(“b”);
            }
        }
    },
    Err(_) => {
        return Err(“c”);
    },
};

All the variables k and m are of type String.I am looking for a way to make the code more readable by removing excessive nested match statements keeping the error handling intact since both the output and the error types are important for the problem.Is it possible to achieve this by unwrap_or_else?

roku675
  • 59
  • 1
  • 5
  • Use the question mark operator: https://stackoverflow.com/questions/42917566/what-is-this-question-mark-operator-about – Colonel Thirty Two Jul 19 '22 at 01:32
  • Hard to test without a runnable example, but this should help: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=56549448940bb256b96104c3bb009c49 – Dogbert Jul 19 '22 at 02:39
  • 1
    @Dogbert That won't compile given sane functions that return `Result`; I think you want `map_err`, not `unwrap_or_else`. – cdhowie Jul 19 '22 at 06:00
  • @cdhowie you're absolutely right, `map_err` is the right one. – Dogbert Jul 19 '22 at 06:02

1 Answers1

0

The .map_err() utility converts a Result to have a new error type, leaving the success type alone. It accepts a closure that consumes the existing error value and returns the new one.

The ? operator will early-return the error in the Err case, and unwrap in the Ok case.

Combining these two allows you to express this same flow succinctly:

get_auth(
    client.get(url).send().map_err(|_| "c")?
    .read_to_string(&mut s).map_err(|_| "b")?
).map_err(|_| "a")?

(I suspect that you actually want to pass s to get_auth() but that's not what the code in your question does, so I'm choosing to represent the code you posted instead of imaginary code that I'm guessing about.)

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • 1
    Also worth mentioning [`.or()`](https://doc.rust-lang.org/1.54.0/core/result/enum.Result.html#method.or) avoids the closure if you don't need the original error, e.g. `client.get (url).send().or (Err ("c"))?` – Jmb Jul 19 '22 at 06:57