1

Is there any way to express the following code in a more concise manner? The function should only continue if the result is Ok(), else it should return a default object. The code I came up with looks kind of unidiomatic, so I wondered if there is a better and more concise way.

fn get_config() -> Config {
    let cfg = match get_config_file_path() { // can return a (custom) PathError
        Ok(c) => c,
        Err(e) => {
            error(&*format!(
                "{} -> Using default configuration",
                e.description
            ));
            return Config::default();
        }
    };
    let cfg_str = match fs::read_to_string(&cfg) { // io::Error
        Ok(c) => c,
        Err(_) => {
            error("Failed to read config file");
            return Config::default();
        }
    };
    toml::from_str(&*cfg_str).unwrap_or_else(|_| { // toml::de::Error
        error("Failed to parse config file");
        Config::default()
    })
}

Edit: My solution:

I created the following macro:

macro_rules! unwrap_or_return {
    ( $e:expr, $c:expr) => {
        match $e {
            Ok(x) => x,
            Err(_) => return $c,
        }
    };
}

fn get_config() -> Config {
    let cfg = unwrap_or_return!(get_config_file_path(), {
        error("Failed to get path to configuration file");
        Config::default()
    });
    let cfg_str = unwrap_or_return!(fs::read_to_string(&cfg), {
        error("Failed to read config file");
        Config::default()
    });
    toml::from_str(&*cfg_str).unwrap_or_else(|_| {
        error("Failed to parse config file");
        Config::default()
    })
}
Ghosty141
  • 21
  • 7
  • It looks like you would like to use the `?` operator but can't because of how your code is set up. I just took your code and modified it slightly by breaking it apart into two functions: `get_config` and `try_get_config`. The `try_get_config` function returns a `Result`. The `get_config` calls that, logs the message and returns the default if an error, or returns the config if successful. Now you can use `?` in `try_get_config`, along with some `map_err` calls to turn the other errors into `String`s. – Harrison McCullough Nov 20 '19 at 21:40
  • @HarrisonMc I found a pretty nice solution using the threads linked above. I created a macro that "wraps" the function in a match. – Ghosty141 Nov 21 '19 at 08:26
  • Glad you got it working. I try to avoid macros if there are other options, but if you found a good solution then that's great :-) – Harrison McCullough Nov 21 '19 at 16:38

0 Answers0