better_config_loader/
ini.rs1use better_config_core::{merge_with_env_uppercase, AbstractConfig, Error, misc};
2use ini::Ini;
3use std::collections::{HashMap, HashSet};
4
5pub trait IniConfig<T = HashMap<String, String>>: AbstractConfig<T> {
7 fn load(target: Option<String>) -> Result<T, Error>
15 where
16 T: Default,
17 HashMap<String, String>: Into<T>,
18 Self: Sized,
19 {
20 Self::load_with_override(target, &HashSet::new())
21 }
22
23 fn load_with_override(target: Option<String>, excluded_keys: &HashSet<String>) -> Result<T, Error>
32 where
33 T: Default,
34 HashMap<String, String>: Into<T>,
35 Self: Sized,
36 {
37 let target = target.or(Some("config.ini".to_string()));
38
39 let mut ini_map = HashMap::new();
40
41 if let Some(target) = target {
42 let file_paths = misc::validate_and_split_paths(&target)?;
43
44 for file_path in file_paths {
45 misc::check_file_accessibility(&file_path)?;
47
48 let ini = Ini::load_from_file(&file_path)
49 .map_err(|e| Error::IoError {
50 operation: format!("load INI file '{}'", file_path),
51 source: Some(Box::new(e)),
52 })?;
53
54 for (section, props) in ini.iter() {
55 let section_prefix = match section {
56 Some(s) => format!("{}.", s),
57 None => String::new(),
58 };
59
60 for (key, value) in props.iter() {
61 ini_map.insert(format!("{}{}", section_prefix, key), value.to_string());
62 }
63 }
64 }
65 }
66
67 let ini_map = merge_with_env_uppercase(ini_map, None, excluded_keys);
69
70 Ok(ini_map.into())
71 }
72}