use std::collections::BTreeSet;
use cargo_metadata::{DependencyKind, PackageId};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum ImpactDomain {
Build,
Development,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum ImpactFallback {
HistoricalResolutionUnavailable,
UnknownDependencyKind,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct ImpactStep {
pub(crate) dependency: PackageId,
pub(crate) dependent: PackageId,
pub(crate) alias: String,
pub(crate) kind: DependencyKind,
pub(crate) target: Option<String>,
pub(crate) optional: bool,
pub(crate) uses_default_features: bool,
pub(crate) features: Vec<String>,
pub(crate) proc_macro: bool,
pub(crate) host: bool,
pub(crate) domain: ImpactDomain,
pub(crate) fallbacks: Vec<ImpactFallback>,
}
#[derive(Debug, Default)]
pub(crate) struct ImpactPropagation {
pub(crate) build: BTreeSet<PackageId>,
pub(crate) development: BTreeSet<PackageId>,
pub(crate) steps: Vec<ImpactStep>,
}
impl ImpactPropagation {
pub(super) fn normalize(&mut self) {
self.development.retain(|package| !self.build.contains(package));
sort_steps(&mut self.steps);
}
}
fn sort_steps(steps: &mut Vec<ImpactStep>) {
steps.sort_by(|left, right| {
(
&left.dependent,
left.domain,
&left.dependency,
&left.alias,
dependency_kind_rank(left.kind),
&left.target,
&left.features,
)
.cmp(&(
&right.dependent,
right.domain,
&right.dependency,
&right.alias,
dependency_kind_rank(right.kind),
&right.target,
&right.features,
))
});
steps.dedup();
}
const fn dependency_kind_rank(kind: DependencyKind) -> u8 {
match kind {
DependencyKind::Normal => 0,
DependencyKind::Development => 1,
DependencyKind::Build => 2,
DependencyKind::Unknown => 3,
}
}