1use serde::de::DeserializeOwned;
2
3pub fn load_config<T>(basename: &str, env_prefix: &str) -> Result<T, config::ConfigError>
9where
10 T: DeserializeOwned,
11{
12 config::Config::builder()
13 .add_source(config::File::with_name(basename).required(false))
14 .add_source(
15 config::Environment::with_prefix(env_prefix)
16 .separator("__")
17 .try_parsing(true),
18 )
19 .build()?
20 .try_deserialize::<T>()
21}
22
23#[cfg(test)]
24mod tests {
25 use super::load_config;
26 use serde::Deserialize;
27 use std::io::Write;
28
29 #[derive(Debug, Deserialize)]
30 struct App {
31 server: Server,
32 }
33
34 #[derive(Debug, Deserialize)]
35 struct Server {
36 port: u16,
37 }
38
39 #[test]
40 fn loads_toml_file() {
41 let dir = tempfile::tempdir().expect("tempdir");
42 let file_path = dir.path().join("app.toml");
43 let mut file = std::fs::File::create(&file_path).expect("create config");
44 writeln!(file, "[server]\nport = 8080").expect("write config");
45
46 let basename = file_path.with_extension("");
47 let app: App =
48 load_config(basename.to_str().expect("utf8 path"), "RSZERO_TEST").expect("load config");
49
50 assert_eq!(app.server.port, 8080);
51 }
52}