diff --git a/crates/pacdef_core/src/grouping/section.rs b/crates/pacdef_core/src/grouping/section.rs index f261937..27ee76b 100644 --- a/crates/pacdef_core/src/grouping/section.rs +++ b/crates/pacdef_core/src/grouping/section.rs @@ -19,27 +19,16 @@ impl Section { } pub(crate) fn try_from_lines<'a>( - iter: &mut Peekable<(impl Iterator + std::fmt::Debug)>, + iter: &mut Peekable>, ) -> Result { - let name = iter - .find(|line| line.starts_with('[')) - .context("finding beginning of next section")? - .trim() - .trim_start_matches('[') - .trim_end_matches(']') - .to_string(); + let name = find_next_section_name(iter)?; let mut packages = HashSet::new(); - // `while let` chains are unstable, unfortunately - while iter.peek().is_some() - && !iter - .peek() - .expect("we checked this is some") - .starts_with('[') - { + + while next_line_might_be_package(iter) { if let Some(package) = Package::try_from(iter.next().expect("we checked this is some")) { - packages.insert(package); + insert_package(package, &mut packages); } } @@ -49,6 +38,37 @@ impl Section { } } +fn insert_package(package: Package, packages: &mut HashSet) { + let package_name = package.name.clone(); + let newly_inserted = packages.insert(package); + + if !newly_inserted { + eprintln!("warning: {package_name} occurs twice in the same section"); + } +} + +fn next_line_might_be_package<'a>(iter: &mut Peekable>) -> bool { + // `while let` chains are unstable, unfortunately + iter.peek().is_some() + && !iter + .peek() + .expect("we checked this is some") + .starts_with('[') +} + +fn find_next_section_name<'a>( + iter: &mut Peekable>, +) -> Result { + let name = iter + .find(|line| line.starts_with('[')) + .context("finding beginning of next section")? + .trim() + .trim_start_matches('[') + .trim_end_matches(']') + .to_string(); + Ok(name) +} + impl Hash for Section { fn hash(&self, state: &mut H) { self.name.hash(state);