use crate::cargo::manifest_analyzer::{DepKey, DepUsage, ManifestAnalyzer};
use crate::config::UnifyConfig;
use std::collections::HashSet;
use std::sync::Arc;
pub struct UnifyCandidate<'a> {
pub dep_key: &'a DepKey,
pub usages: Vec<&'a DepUsage>,
}
pub struct CandidateIterator<'a> {
manifests: &'a ManifestAnalyzer,
config: &'a UnifyConfig,
processed: HashSet<Arc<str>>,
all_deps: Vec<&'a DepKey>,
index: usize,
}
impl<'a> CandidateIterator<'a> {
pub fn new(manifests: &'a ManifestAnalyzer, config: &'a UnifyConfig) -> Self {
let all_deps = manifests.all_dependencies();
Self {
manifests,
config,
processed: HashSet::new(),
all_deps,
index: 0,
}
}
fn should_skip(&self, dep_key: &DepKey, usage_count: usize) -> bool {
if self.config.exclude.iter().any(|s| s.as_str() == &*dep_key.name) {
return true;
}
if usage_count < 2 && !self.config.include.iter().any(|s| s.as_str() == &*dep_key.name) {
return true;
}
if dep_key.renamed_from.is_some() && !self.config.include_renamed {
return true;
}
false
}
}
impl<'a> Iterator for CandidateIterator<'a> {
type Item = UnifyCandidate<'a>;
fn next(&mut self) -> Option<Self::Item> {
while self.index < self.all_deps.len() {
let dep_key = self.all_deps[self.index];
self.index += 1;
if self.config.include_renamed {
if self.processed.contains(&dep_key.name) {
continue;
}
let usage_count = self.manifests.package_usage_count(&dep_key.name);
if self.should_skip(dep_key, usage_count) {
continue;
}
self.processed.insert(Arc::clone(&dep_key.name));
let usages = self.manifests.get_package_usage_sites(&dep_key.name);
return Some(UnifyCandidate { dep_key, usages });
} else {
let usage_count = self.manifests.usage_count(dep_key);
if self.should_skip(dep_key, usage_count) {
continue;
}
let usages = self.manifests.get_usage_sites(dep_key);
return Some(UnifyCandidate { dep_key, usages });
}
}
None
}
}