@@ -19,27 +19,16 @@ impl Section {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn try_from_lines<'a>(
|
pub(crate) fn try_from_lines<'a>(
|
||||||
iter: &mut Peekable<(impl Iterator<Item = &'a str> + std::fmt::Debug)>,
|
iter: &mut Peekable<impl Iterator<Item = &'a str>>,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let name = iter
|
let name = find_next_section_name(iter)?;
|
||||||
.find(|line| line.starts_with('['))
|
|
||||||
.context("finding beginning of next section")?
|
|
||||||
.trim()
|
|
||||||
.trim_start_matches('[')
|
|
||||||
.trim_end_matches(']')
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
let mut packages = HashSet::new();
|
let mut packages = HashSet::new();
|
||||||
// `while let` chains are unstable, unfortunately
|
|
||||||
while iter.peek().is_some()
|
while next_line_might_be_package(iter) {
|
||||||
&& !iter
|
|
||||||
.peek()
|
|
||||||
.expect("we checked this is some")
|
|
||||||
.starts_with('[')
|
|
||||||
{
|
|
||||||
if let Some(package) = Package::try_from(iter.next().expect("we checked this is some"))
|
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<Package>) {
|
||||||
|
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<impl Iterator<Item = &'a str>>) -> 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<impl Iterator<Item = &'a str>>,
|
||||||
|
) -> Result<String> {
|
||||||
|
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 {
|
impl Hash for Section {
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.name.hash(state);
|
self.name.hash(state);
|
||||||
|
|||||||
Reference in New Issue
Block a user