How reduce the nested if and indents?

I have the following code which contains a lot of nested if (some are Result and some are Option. Is it possible to reduce the nested if and have fewer indents?
Is there something like the post operator ? to simplify the code?

The code is focusing on the successful cases and ignore if there is anything wrong.

           let res = client
                .post(...
                ))
                .header("Authorization", &config_env::get__api_token())
                .header("Accept", "application/json")
                .json(&task)
                .send()
                .await;
            match res {
                Ok(body) => {
                    println!("Succeed posting task {:?}", body);
                    if body.status() == reqwest::StatusCode::OK {
                        if let Ok(result) = body.json::<serde_json::Value>().await {
                            if let Some(code) = result.get("code") {
                                if let Some(code) = code.as_u64() {
                                    if code != 200 {
                                        
                                        if let Err(e) = github::issue::post_issue_comment(...
                                        ).await
                                        {
                                            eprintln!("{}", e);
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        eprintln!("Fail to send job with status code: {}.", body.status());
                    }

The approach I can think of is to use premature return like

if not_ok {
  return;
}
if not_ok {
 return;
}
...

but I still need to write a lot of return.

Yes. That's what the ? operator is for: ? - Rust By Example

For cases where you want a different error handling than what you get from the question mark operator, here are some different things you can do:

You can match on the value and return if there isn't any value.

let code = match result.get("code") {
    Some(code) => code,
    None => return,
};

There are also methods like ok_or_else, which let you change an Option<T> into an Result<T, E> with a custom error. This then lets you use the question mark operator to return the custom error if the option is None.

let code = result.get("code")
    .ok_or_else(|| /* error you want to return goes here */)?;
3 Likes

The ? operator cannot work here as there are Result and Option mixed together.

The ok_or_else method that I mentioned can be used to allow ? with an Option in a method returning a Result.

2 Likes

Thanks! I'll try it and see if the code will be simplified.