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