### Example INI File Structure Source: https://github.com/qedk/ini-rs/blob/master/README.md Demonstrates a typical INI file structure with case-insensitive section headers, key-value pairs, comments, and whitespace handling. Values are always treated as strings. ```INI [section headers are case-insensitive] [ section headers are case-insensitive ] are the section headers above same? = yes sectionheaders_and_keysarestored_in_lowercase? = yes keys_are_also_case_insensitive = Values are case sensitive ;anything after a comment symbol is ignored #this is also a comment spaces in keys=allowed ;and everything before this is still valid! spaces in values=allowed as well spaces around the delimiter = also OK [All values are strings] values like this= 0000 or this= 0.999 are they treated as numbers? = no integers, floats and booleans are held as= strings [value-less?] a_valueless_key_has_None this key has an empty string value has Some("") = [indented sections] can_values_be_as_well = True purpose = formatting for readability is_this_same = yes is_this_same=yes ``` -------------------------------- ### Handle Value-less Keys and Convert Types (Rust) Source: https://context7.com/qedk/ini-rs/llms.txt Illustrates how to work with INI keys that lack values (represented as `None`) and keys with empty values (represented as `Some("")`). It emphasizes that all values are initially strings and require manual parsing for numeric or boolean types. ```rust #[macro_use] extern crate ini; fn main() { let config_str = "[features] debug_mode verbose = timeout = 30 retry_count = 5 use_ssl = true api_endpoint = https://api.example.com [default] optimization_level = 2"; let config = inistr!(config_str); // Check for value-less key (returns None) let debug_mode = config["features"].get("debug_mode"); assert!(debug_mode.is_some() && debug_mode.unwrap().is_none()); let is_debug = debug_mode.is_some(); // Key with empty value (returns Some("")) let verbose = config["features"]["verbose"].clone(); assert_eq!(verbose, Some(String::new())); // Parse numeric values let timeout = config["features"]["timeout"] .clone() .unwrap() .parse::() .expect("Invalid timeout"); let retry_count = config["features"]["retry_count"] .clone() .unwrap() .parse::() .unwrap_or(3); // Parse boolean values let use_ssl = config["features"]["use_ssl"] .clone() .unwrap() .parse::() .unwrap_or(false); // String values used directly let api_endpoint = config["features"]["api_endpoint"].clone().unwrap(); println!("Debug: {}, Timeout: {}s, SSL: {}, API: {}", is_debug, timeout, use_ssl, api_endpoint); // Default section for section-less keys let optimization = config["default"]["optimization_level"] .clone() .unwrap() .parse::() .unwrap(); } ``` -------------------------------- ### Parse INI string using `inistr!` macro Source: https://context7.com/qedk/ini-rs/llms.txt Demonstrates parsing an INI configuration string into a nested HashMap using the `inistr!` macro provided by the `ini-rs` crate. This macro handles various INI syntax elements like comments, whitespace, and special characters. The output is a HashMap that can be accessed using standard Rust indexing. ```rust let config_str = r#" # File paths can contain spaces data_dir = /var/lib/app data ; everything before ; is kept log_file=/var/log/app.log#this is still part of the value ; Special case: # inside value is kept if not preceded by space [ indented.section ] nested_key = nested value ; Indentation is ignored"#; let config = inistr!(config_str); // Whitespace trimmed from section names assert!(config.contains_key("server")); assert!(config.contains_key("indented.section")); // Whitespace trimmed from keys and values assert_eq!(config["server"]["host"].clone().unwrap(), "localhost"); assert_eq!(config["server"]["port"].clone().unwrap(), "8080"); // Values trimmed but internal spaces preserved assert_eq!(config["paths"]["data_dir"].clone().unwrap(), "/var/lib/app data"); // Hash in value without preceding space is kept assert_eq!( config["paths"]["log_file"].clone().unwrap(), "/var/log/app.log#this is still part of the value" ); // Indented keys work normally assert_eq!(config["indented.section"]["nested_key"].clone().unwrap(), "nested value"); // Max connections parsed despite comment let max_conn = config["server"]["max_connections"] .clone() .unwrap() .parse::() .unwrap(); assert_eq!(max_conn, 100); ``` -------------------------------- ### Parsing INI files with `ini!` macro in Rust Source: https://github.com/qedk/ini-rs/blob/master/README.md The `ini!` macro reads configuration from specified files and returns a HashMap. It panics on error by default. Use the `safe` option for graceful error handling, returning a `Result` type. ```rust #[macro_use] extern crate ini; fn main() { let map = ini!("...path/to/file"); // Proceed to use normal HashMap functions on the map: let val = map["section"]["key"].clone().unwrap(); // To load multiple files, just do: let (map1, map2, map3) = ini!("path/to/file1", "path/to/file2", "path/to/file3"); // Each map is a cloned hashmap with no relation to other ones } ``` ```rust let map = ini!(safe "...path/to/file"); // Proceed to use normal HashMap functions on the map: let val = map.unwrap()["section"]["key"].clone().unwrap(); // Note the extra unwrap here, which is required because our HashMap is inside a Result type. ``` -------------------------------- ### Handle Comments and Whitespace in INI (Rust) Source: https://context7.com/qedk/ini-rs/llms.txt Shows how the parser handles comments, supporting both semicolon (`;`) and hash (`#`) symbols. It also details the automatic trimming of leading and trailing whitespace from section headers, keys, and values, ensuring cleaner data processing. ```rust #[macro_use] extern crate ini; fn main() { let config_str = "; This is a configuration file # Another comment style [ server ] ; Section with whitespace host = localhost ; Value with spaces around port=8080 # Different comment style ; Comments on their own lines max_connections = 100 ; inline comment [paths] "; } ] } ] } ``` ``` -------------------------------- ### Parsing INI strings with `inistr!` macro in Rust Source: https://github.com/qedk/ini-rs/blob/master/README.md The `inistr!` macro parses configuration directly from string literals or variables, returning a HashMap. Similar to `ini!`, it panics on error by default, but the `safe` option provides `Result`-based error handling. ```rust #[macro_use] extern crate ini; fn main() { let configstring = "[section] key = value top = secret"; let map = inistr!(configstring); // Proceed to use normal HashMap functions on the map: let val = map["section"]["top"].clone().unwrap(); // The type of the map is HashMap>> assert_eq!(val, "secret"); // value accessible! // To load multiple string, just do: let (map1, map2, map3) = inistr!(&String::from(configstring), configstring, "[section] key = value top = secret"); // Each map is a cloned hashmap with no relation to other ones } ``` ```rust let map = inistr!(safe strvariable_or_strliteral); // Proceed to use normal HashMap functions on the map: let val = map.unwrap()["section"]["key"].clone().unwrap(); // Note the extra unwrap here, which is required because our HashMap is inside a Result type. ``` -------------------------------- ### Safe INI File Loading with `ini!` Macro Source: https://context7.com/qedk/ini-rs/llms.txt The `ini!` macro with the `safe` keyword provides error handling for INI file loading. It returns a `Result>>, String>`, allowing graceful management of file read or parse errors. Multiple safe loads can be combined using `.or()`. ```rust #[macro_use] extern crate ini; use std::collections::HashMap; fn main() { // Safe loading returns Result type let config_result = ini!(safe "app.ini"); match config_result { Ok(config) => { // Handle successful load if let Some(section) = config.get("server") { if let Some(Some(port)) = section.get("port") { println!("Server port: {}", port); } else { println!("Port not configured, using default"); } } } Err(error) => { // Handle file read or parse errors eprintln!("Failed to load config: {}", error); eprintln!("Using default configuration"); } } // Multiple safe loads let (config1, config2) = ini!(safe "primary.ini", safe "fallback.ini"); let final_config = config1.or(config2).unwrap_or_else(|_| { HashMap::new() }); } ``` -------------------------------- ### Load INI File from Path using `ini!` Macro Source: https://context7.com/qedk/ini-rs/llms.txt The `ini!` macro loads one or more INI files from the filesystem. It returns a `HashMap>>` representing sections and key-value pairs. The macro panics on file read or parse errors. Values can be accessed directly and parsed into desired types. ```rust #[macro_use] extern crate ini; fn main() { // Load a single INI file let config = ini!("config.ini"); // Access values using section and key names let database_host = config["database"]["host"].clone().unwrap(); let port_str = config["database"]["port"].clone().unwrap(); let port: u16 = port_str.parse().unwrap(); println!("Connecting to {}:{}", database_host, port); // Load multiple files simultaneously let (dev_config, prod_config, test_config) = ini!( "config.dev.ini", "config.prod.ini", "config.test.ini" ); // Each map is independent assert_ne!(dev_config["database"]["host"], prod_config["database"]["host"]); } ``` -------------------------------- ### Manual Type Parsing from INI values in Rust Source: https://github.com/qedk/ini-rs/blob/master/README.md Configuration values are stored as strings by default. This snippet demonstrates how to manually parse these string values into other data types like integers using Rust's built-in parsing methods. ```rust let my_string = map["section"]["key"].clone().unwrap(); let my_int = my_string.parse::().unwrap(); ``` -------------------------------- ### Parse INI String with `inistr!` Macro Source: https://context7.com/qedk/ini-rs/llms.txt The `inistr!` macro parses INI-formatted content directly from strings without requiring filesystem access. It returns the same nested HashMap structure as the `ini!` macro, useful for embedded configurations or dynamically generated INI data. It also supports parsing multiple strings or string references. ```rust #[macro_use] extern crate ini; fn main() { let config_str = "[database]\nhost = localhost\nport = 5432\nusername = admin\npassword = secret123\n [logging]\nlevel = debug\nfile = /var/log/app.log\n [feature_flags]\nenable_cache = true\nmax_connections = 100"; let config = inistr!(config_str); // Extract and use configuration values let db_host = config["database"]["host"].clone().unwrap(); let db_port = config["database"]["port"].clone().unwrap().parse::().unwrap(); let log_level = config["logging"]["level"].clone().unwrap(); println!("Database: {}:{}", db_host, db_port); println!("Log level: {}", log_level); // Parse multiple strings at once let alternate_config = "[database]\nhost = db.example.com\nport = 3306"; let (config1, config2) = inistr!(config_str, alternate_config); // Also supports string references let config_string = String::from(config_str); let config3 = inistr!(&config_string); } ``` -------------------------------- ### Parse INI String Safely with Error Handling (Rust) Source: https://context7.com/qedk/ini-rs/llms.txt Demonstrates using the `inistr!` macro with the `safe` keyword to parse INI strings. It returns a `Result` type, allowing for robust error handling of invalid INI syntax. This snippet also shows how to validate multiple INI strings simultaneously. ```rust #[macro_use] extern crate ini; fn main() { let user_input = "[settings]\ntheme = dark language = en [notifications] email = enabled push = disabled"; let config_result = inistr!(safe user_input); match config_result { Ok(config) => { // Safely access parsed configuration let theme = config.get("settings") .and_then(|s| s.get("theme")) .and_then(|v| v.clone()) .unwrap_or_else(|| "light".to_string()); let email_enabled = config["notifications"]["email"] .clone() .unwrap() == "enabled"; println!("Theme: {}, Email notifications: {}", theme, email_enabled); } Err(parse_error) => { eprintln!("Invalid INI format: {}", parse_error); } } // Validate multiple configuration strings let (result1, result2) = inistr!( safe "[valid]\nkey=value", safe "[another]\nkey2=value2" ); if result1.is_ok() && result2.is_ok() { println!("All configurations valid"); } } ``` -------------------------------- ### Access INI Data Case-Insensitively (Rust) Source: https://context7.com/qedk/ini-rs/llms.txt Explains that section headers and keys in the parsed INI data are automatically converted to lowercase, enabling case-insensitive access. Values, however, retain their original casing. This snippet demonstrates this behavior, including how duplicate keys are resolved. ```rust #[macro_use] extern crate ini; fn main() { let config_str = "[DATABASE] Host = localhost PORT = 5432 UserName = admin [Database] CONNECTION_TIMEOUT = 30 [api.ENDPOINTS] UsersAPI = /api/v1/users"; let config = inistr!(config_str); // All section names are lowercase assert!(config.contains_key("database")); assert!(!config.contains_key("DATABASE")); // All keys are lowercase (duplicate sections merge) let db_config = &config["database"]; assert_eq!(db_config["host"].clone().unwrap(), "localhost"); assert_eq!(db_config["port"].clone().unwrap(), "5432"); assert_eq!(db_config["username"].clone().unwrap(), "admin"); assert_eq!(db_config["connection_timeout"].clone().unwrap(), "30"); // Values preserve their original case let api_path = config["api.endpoints"]["usersapi"].clone().unwrap(); assert_eq!(api_path, "/api/v1/users"); // Last value wins for duplicate keys let test_str = "[section] key = first_value key = second_value KEY = final_value"; let test_config = inistr!(test_str); assert_eq!(test_config["section"]["key"].clone().unwrap(), "final_value"); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.