Skip to content

Commit 1d34536

Browse files
feat: add support for nested sections
1 parent 2150227 commit 1d34536

File tree

2 files changed

+60
-51
lines changed

2 files changed

+60
-51
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,11 @@ case-insensitive = ["unicase"]
4040
# [[A]]
4141
# Key=value
4242
brackets-in-section-names = []
43+
# Allow parsing of nested sections
44+
#
45+
# For example:
46+
# [Section][Subsection]
47+
# key=value
48+
#
49+
# That appears in KDE Configuration files
50+
nested-sections = []

src/lib.rs

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@
4444
4545
use std::{
4646
borrow::Cow,
47-
char,
48-
error,
47+
char, error,
4948
fmt::{self, Display},
5049
fs::{File, OpenOptions},
5150
io::{self, Read, Seek, SeekFrom, Write},
@@ -300,53 +299,51 @@ impl Default for WriteOption {
300299
}
301300
}
302301

302+
#[cfg(all(feature = "case-insensitive", not(feature = "nested-sections")))]
303+
pub type SectionKey = Option<UniCase<String>>;
304+
#[cfg(all(feature = "case-insensitive", feature = "nested-sections"))]
305+
pub type SectionKey = Option<Vec<UniCase<String>>>;
306+
#[cfg(all(not(feature = "case-insensitive"), not(feature = "nested-sections")))]
307+
pub type SectionKey = Option<String>;
308+
#[cfg(all(not(feature = "case-insensitive"), feature = "nested-sections"))]
309+
pub type SectionKey = Option<Vec<String>>;
310+
303311
cfg_if! {
304312
if #[cfg(feature = "case-insensitive")] {
305-
/// Internal storage of section's key
306-
pub type SectionKey = Option<UniCase<String>>;
307-
/// Internal storage of property's key
308-
pub type PropertyKey = UniCase<String>;
309-
310-
macro_rules! property_get_key {
311-
($s:expr) => {
312-
&UniCase::from($s)
313-
};
314-
}
315-
316-
macro_rules! property_insert_key {
317-
($s:expr) => {
318-
UniCase::from($s)
319-
};
320-
}
321-
322-
macro_rules! section_key {
323-
($s:expr) => {
324-
$s.map(|s| UniCase::from(s.into()))
325-
};
313+
cfg_if! {
314+
if #[cfg(feature = "nested-sections")] {
315+
macro_rules! section_key {
316+
($s:expr) => {
317+
$s.map(|s| {
318+
s.split("][")
319+
.map(|part| UniCase::from(part.to_string()))
320+
.collect::<Vec<_>>()
321+
})
322+
};
323+
}
324+
} else {
325+
macro_rules! section_key {
326+
($s:expr) => {
327+
$s.map(|s| UniCase::from(s.into()))
328+
};
329+
}
330+
}
326331
}
327-
328332
} else {
329-
/// Internal storage of section's key
330-
pub type SectionKey = Option<String>;
331-
/// Internal storage of property's key
332-
pub type PropertyKey = String;
333-
334-
macro_rules! property_get_key {
335-
($s:expr) => {
336-
$s
337-
};
338-
}
339-
340-
macro_rules! property_insert_key {
341-
($s:expr) => {
342-
$s
343-
};
344-
}
345-
346-
macro_rules! section_key {
347-
($s:expr) => {
348-
$s.map(Into::into)
349-
};
333+
cfg_if! {
334+
if #[cfg(feature = "nested-sections")] {
335+
macro_rules! section_key {
336+
($s:expr) => {
337+
$s.map(|s| s.split("][").map(Into::into).collect::<Vec<_>>())
338+
};
339+
}
340+
} else {
341+
macro_rules! section_key {
342+
($s:expr) => {
343+
$s.map(Into::into)
344+
};
345+
}
346+
}
350347
}
351348
}
352349
}
@@ -959,12 +956,16 @@ impl Ini {
959956
}
960957

961958
if let Some(ref section) = *section {
962-
write!(
963-
writer,
964-
"[{}]{}",
965-
escape_str(&section[..], opt.escape_policy),
966-
opt.line_separator
967-
)?;
959+
#[cfg(feature = "nested-sections")]
960+
let section_str = {
961+
section
962+
.iter()
963+
.map(|part| format!("[{}]", escape_str(part, opt.escape_policy)))
964+
.collect::<String>()
965+
};
966+
#[cfg(not(feature = "nested-sections"))]
967+
let section_str = format!("[{}]", escape_str(section, opt.escape_policy));
968+
write!(writer, "{}{}", section_str, opt.line_separator)?;
968969
}
969970
for (k, v) in props.iter() {
970971
let k_str = escape_str(k, opt.escape_policy);

0 commit comments

Comments
 (0)