better_config_loader/
ini.rs

1use better_config_core::{AbstractConfig, Error};
2use better_config_core::misc;
3use ini::Ini;
4use std::collections::HashMap;
5
6/// Indicates that structure can be initialized from INI file.
7pub trait IniConfig<T = HashMap<String, String>>: AbstractConfig<T> {
8    /// Load specified INI file and initialize the structure.
9    ///
10    /// # Arguments
11    /// * `target` - Path to the INI file.
12    ///
13    /// # Errors
14    /// * `Error::LoadFileError` - If the specified INI file cannot be loaded or parsed.
15    fn load(target: Option<String>) -> Result<T, Error>
16    where
17        T: Default,
18        HashMap<String, String>: Into<T>,
19        Self: Sized,
20    {
21        let target = target.or(Some("config.ini".to_string()));
22
23        let mut ini_map = HashMap::new();
24
25        if let Some(target) = target {
26            let file_paths = misc::validate_and_split_paths(&target)?;
27
28            for file_path in file_paths {
29                // Check file accessibility before reading
30                misc::check_file_accessibility(&file_path)?;
31
32                let ini = Ini::load_from_file(&file_path)
33                    .map_err(|e| Error::IoError {
34                        operation: format!("load INI file '{}'", file_path),
35                        source: Some(Box::new(e)),
36                    })?;
37
38                for (section, props) in ini.iter() {
39                    let section_prefix = match section {
40                        Some(s) => format!("{}.", s),
41                        None => String::new(),
42                    };
43
44                    for (key, value) in props.iter() {
45                        ini_map.insert(format!("{}{}", section_prefix, key), value.to_string());
46                    }
47                }
48            }
49        }
50
51        Ok(ini_map.into())
52    }
53}