Hey there everyone
I have a rust workspace so I don't duplicate compilation artifacts between a serial and a parallel version of a code. I.e. my workspace looks roughly like this
Now my question. I wanna be able to run the parallel code either from the workspace folder or from the parallel folder. In order to read the config.toml that holds some parameters for my code I need to check two possible paths, depending on what my working directory is. I do it with the following code:
pub fn read_config() -> Config {
let path = Path::new("parallel/config.toml");
let path = if path.exists() {
path
} else {
Path::new("config.toml")
};
let config = config::Config::builder()
.add_source(config::File::with_name(path.to_str().unwrap()))
.add_source(config::Environment::with_prefix("MASS"))
.build()
.unwrap();
let settings: Config = config.try_deserialize().unwrap();
settings
}
Can you give me feedback on this. Is there a more idiomatic way to see whether one of two paths exists?
If that is specifically what you want then your solution looks fine. Are you ignoring the file if it doesn't exist? I.e. your default config file will be config.toml, if you don't find parallel/config.toml relative to your current directory; if the ./config.toml does not exist are you panicing or silently ignore the fact that your file wasn't found? Could be an interesting design choice if you haven't made it already.
If you want to increase the usability of your API beyond the use-case of just "execute from workspace or workspace/parallel", I personally like the dotenv API. It looks in your current directory for a .env file (config.toml in your case). If it does not find it, it recursively traverses the path all the way to the root directory, looking for a .env (config.toml) file.
Another project that has very strong configuration capabilities is Cargo. Cargo looks for its config.toml pretty much everywhere , with the flexibility of overriding the configuration for different projects. See here: Configuration - The Cargo Book.