use std::collections::BTreeSet;
use serde::Serialize;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct GraphDelta {
pub removed_nodes: Vec<String>,
pub removed_edges: Vec<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct SurfaceDelta {
pub added: Vec<String>,
pub removed: Vec<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
pub struct ImpactedSurface {
pub base_only: Vec<String>,
pub head_only: Vec<String>,
pub shared: Vec<String>,
pub removed_nodes: Vec<String>,
pub removed_edges: Vec<String>,
pub removed_surfaces: Vec<String>,
}
impl ImpactedSurface {
#[must_use]
pub fn all_nodes(&self) -> Vec<String> {
let mut out: BTreeSet<&String> = BTreeSet::new();
for list in [
&self.base_only,
&self.head_only,
&self.shared,
&self.removed_nodes,
] {
out.extend(list.iter());
}
out.into_iter().cloned().collect()
}
#[must_use]
pub fn has_removals(&self) -> bool {
!self.removed_nodes.is_empty()
|| !self.removed_edges.is_empty()
|| !self.removed_surfaces.is_empty()
}
#[must_use]
pub fn missed_by_head_only(&self) -> usize {
let head: BTreeSet<&String> = self.head_only.iter().chain(self.shared.iter()).collect();
self.base_only
.iter()
.chain(self.removed_nodes.iter())
.collect::<BTreeSet<&String>>()
.into_iter()
.filter(|item| !head.contains(*item))
.count()
}
}
#[must_use]
pub fn impacted_surface(
base_impact: &[String],
head_impact: &[String],
graph: &GraphDelta,
surfaces: &SurfaceDelta,
) -> ImpactedSurface {
let base: BTreeSet<&String> = base_impact.iter().collect();
let head: BTreeSet<&String> = head_impact.iter().collect();
ImpactedSurface {
base_only: base.difference(&head).map(|item| (*item).clone()).collect(),
head_only: head.difference(&base).map(|item| (*item).clone()).collect(),
shared: base
.intersection(&head)
.map(|item| (*item).clone())
.collect(),
removed_nodes: unique(&graph.removed_nodes),
removed_edges: unique(&graph.removed_edges),
removed_surfaces: unique(&surfaces.removed),
}
}
fn unique(values: &[String]) -> Vec<String> {
let set: BTreeSet<&String> = values.iter().collect();
set.into_iter().cloned().collect()
}