sbom_tools/diff/
vertex.rs1use crate::model::CanonicalId;
4use std::hash::{Hash, Hasher};
5
6#[derive(Debug, Clone)]
11pub struct DiffVertex {
12 pub left_pos: Option<CanonicalId>,
14 pub right_pos: Option<CanonicalId>,
16 pub processed_together: Vec<CanonicalId>,
18}
19
20impl DiffVertex {
21 #[must_use]
23 pub const fn new(left_pos: Option<CanonicalId>, right_pos: Option<CanonicalId>) -> Self {
24 Self {
25 left_pos,
26 right_pos,
27 processed_together: Vec::new(),
28 }
29 }
30
31 #[must_use]
33 pub const fn start() -> Self {
34 Self::new(None, None)
35 }
36
37 #[must_use]
39 pub fn is_end(&self) -> bool {
40 self.left_pos.is_none() && self.right_pos.is_none() && !self.processed_together.is_empty()
41 }
42}
43
44impl PartialEq for DiffVertex {
45 fn eq(&self, other: &Self) -> bool {
46 self.left_pos == other.left_pos && self.right_pos == other.right_pos
47 }
48}
49
50impl Eq for DiffVertex {}
51
52impl Hash for DiffVertex {
53 fn hash<H: Hasher>(&self, state: &mut H) {
54 self.left_pos.hash(state);
55 self.right_pos.hash(state);
56 }
57}
58
59#[derive(Debug, Clone)]
61#[allow(dead_code)]
62pub enum DiffEdge {
63 ComponentRemoved {
65 component_id: CanonicalId,
66 cost: u32,
67 },
68 ComponentAdded {
70 component_id: CanonicalId,
71 cost: u32,
72 },
73 VersionChanged {
75 component_id: CanonicalId,
76 old_version: String,
77 new_version: String,
78 cost: u32,
79 },
80 LicenseChanged {
82 component_id: CanonicalId,
83 cost: u32,
84 },
85 SupplierChanged {
87 component_id: CanonicalId,
88 cost: u32,
89 },
90 VulnerabilityIntroduced {
92 component_id: CanonicalId,
93 vuln_id: String,
94 cost: u32,
95 },
96 VulnerabilityResolved {
98 component_id: CanonicalId,
99 vuln_id: String,
100 reward: i32,
101 },
102 DependencyAdded {
104 from: CanonicalId,
105 to: CanonicalId,
106 cost: u32,
107 },
108 DependencyRemoved {
110 from: CanonicalId,
111 to: CanonicalId,
112 cost: u32,
113 },
114 ComponentUnchanged { component_id: CanonicalId },
116}
117
118#[allow(dead_code)]
119impl DiffEdge {
120 pub const fn cost(&self) -> i32 {
122 match self {
123 Self::ComponentRemoved { cost, .. }
124 | Self::ComponentAdded { cost, .. }
125 | Self::VersionChanged { cost, .. }
126 | Self::LicenseChanged { cost, .. }
127 | Self::SupplierChanged { cost, .. }
128 | Self::VulnerabilityIntroduced { cost, .. }
129 | Self::DependencyAdded { cost, .. }
130 | Self::DependencyRemoved { cost, .. } => *cost as i32,
131 Self::VulnerabilityResolved { reward, .. } => *reward,
132 Self::ComponentUnchanged { .. } => 0,
133 }
134 }
135
136 pub const fn is_change(&self) -> bool {
138 !matches!(self, Self::ComponentUnchanged { .. })
139 }
140}