rust 42 lines · 9 steps

Parsing INI files in Rust

A streaming parser that reads an INI file line by line into a nested map of sections and key-value pairs.

Explained by highlit
1use std::collections::HashMap;
2use std::fs::File;
3use std::io::{self, BufRead, BufReader};
4use std::path::Path;
5 
6type Ini = HashMap<String, HashMap<String, String>>;
7 
8pub fn parse_ini<P: AsRef<Path>>(path: P) -> io::Result<Ini> {
9 let reader = BufReader::new(File::open(path)?);
10 let mut sections: Ini = HashMap::new();
11 let mut current = String::new();
12 sections.entry(current.clone()).or_default();
13 
14 for line in reader.lines() {
15 let line = line?;
16 let trimmed = line.trim();
17 
18 if trimmed.is_empty() || trimmed.starts_with('#') || trimmed.starts_with(';') {
19 continue;
20 }
21 
22 if let Some(name) = trimmed.strip_prefix('[').and_then(|s| s.strip_suffix(']')) {
23 current = name.trim().to_string();
24 sections.entry(current.clone()).or_default();
25 continue;
26 }
27 
28 if let Some((key, value)) = trimmed.split_once('=') {
29 let value = value.trim();
30 let value = value
31 .strip_prefix('"')
32 .and_then(|v| v.strip_suffix('"'))
33 .unwrap_or(value);
34 sections
35 .get_mut(&current)
36 .unwrap()
37 .insert(key.trim().to_string(), value.to_string());
38 }
39 }
40 
41 Ok(sections)
42}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Tracking a mutable current-section string lets a flat line loop build a nested structure.
  2. 2The ? operator threads I/O failures out cleanly so the parser body stays focused on parsing.
  3. 3or_default and get_mut give ergonomic insert-or-fetch access to nested HashMaps without manual existence checks.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Parsing INI files in Rust — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code