use super::candidates::Candidates;
use super::pattern::Pattern;
#[derive(Debug, Clone)]
pub(crate) struct Catalog {
at: Vec<Option<Pattern>>,
interior: Vec<bool>,
}
impl Catalog {
pub(crate) fn elect(candidates: &Candidates, supports: impl Fn(&Pattern) -> bool) -> Self {
let length = candidates.length();
let mut catalog = Self {
at: vec![None; length],
interior: vec![false; length],
};
let mut claimed = vec![false; length];
for candidate in candidates.iter() {
if !supports(&candidate.pattern) || claimed[candidate.root] {
continue;
}
if candidate
.interiors
.iter()
.chain(candidate.named.iter())
.any(|&node| claimed[node])
{
continue;
}
claimed[candidate.root] = true;
for &node in candidate.interiors.iter().chain(candidate.named.iter()) {
claimed[node] = true;
catalog.interior[node] = true;
}
catalog.at[candidate.root] = Some(candidate.pattern.clone());
}
catalog
}
pub(crate) fn at(&self, index: usize) -> Option<&Pattern> {
self.at[index].as_ref()
}
pub(crate) fn interior(&self, index: usize) -> bool {
self.interior[index]
}
pub(crate) fn groups(&self) -> usize {
self.at.iter().flatten().count()
}
pub(crate) fn entries(&self) -> impl Iterator<Item = (usize, &Pattern)> {
self.at
.iter()
.enumerate()
.filter_map(|(index, pattern)| pattern.as_ref().map(|pattern| (index, pattern)))
}
}
#[cfg(test)]
#[path = "tests/catalog_tests.rs"]
mod tests;