1use serde::{Deserialize, Serialize};
2
3use crate::{Capability, CapabilityFinding, CapabilityProfile};
4
5#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq)]
7pub struct CapabilityDiff {
8 pub added: Vec<CapabilityFinding>,
10 pub removed: Vec<CapabilityFinding>,
12 pub new_capabilities: Vec<Capability>,
14 pub dropped_capabilities: Vec<Capability>,
16}
17
18impl CapabilityDiff {
19 pub fn compute(old: &CapabilityProfile, new: &CapabilityProfile) -> Self {
21 let added: Vec<CapabilityFinding> = new
22 .findings
23 .iter()
24 .filter(|f| !old.findings.contains(f))
25 .cloned()
26 .collect();
27
28 let removed: Vec<CapabilityFinding> = old
29 .findings
30 .iter()
31 .filter(|f| !new.findings.contains(f))
32 .cloned()
33 .collect();
34
35 let old_caps = old.capabilities();
36 let new_caps = new.capabilities();
37
38 let new_capabilities: Vec<Capability> = new_caps
39 .iter()
40 .filter(|c| !old_caps.contains(c))
41 .copied()
42 .collect();
43
44 let dropped_capabilities: Vec<Capability> = old_caps
45 .iter()
46 .filter(|c| !new_caps.contains(c))
47 .copied()
48 .collect();
49
50 Self {
51 added,
52 removed,
53 new_capabilities,
54 dropped_capabilities,
55 }
56 }
57}