1use std::fmt::Debug;
2use std::hash::Hash;
3
4use crate::TwoPTwoPGraphError;
5
6pub trait TwoPTwoPId<Id> {
8 fn id(&self) -> &Id;
10}
11
12pub trait TwoPTwoPAddVertex<Id>: TwoPTwoPId<Id> {}
14
15pub trait TwoPTwoPRemoveVertex<Id>: TwoPTwoPId<Id> {
17 fn add_vertex_id(&self) -> &Id;
19}
20
21pub trait TwoPTwoPAddEdge<Id>: TwoPTwoPId<Id> {
23 fn source(&self) -> &Id;
25 fn target(&self) -> &Id;
27}
28
29pub trait TwoPTwoPRemoveEdge<Id>: TwoPTwoPId<Id> {
31 fn add_edge_id(&self) -> &Id;
33}
34
35pub enum UpdateType {
37 AtSource,
39 Downstream,
41}
42
43#[derive(Clone, Debug, PartialEq, Eq)]
45pub enum UpdateOperation<VA, VR, EA, ER> {
46 AddVertex(VA),
47 RemoveVertex(VR),
48 AddEdge(EA),
49 RemoveEdge(ER),
50}
51
52#[derive(Clone, Debug)]
65pub struct TwoPTwoPGraph<VA, VR, EA, ER, I>
66where
67 VA: Clone + TwoPTwoPAddVertex<I>,
68 VR: Clone + TwoPTwoPRemoveVertex<I>,
69 EA: Clone + TwoPTwoPAddEdge<I>,
70 ER: Clone + TwoPTwoPRemoveEdge<I>,
71 I: Eq + Hash + Debug + Clone,
72{
73 vertices_added: Vec<VA>,
74 vertices_removed: Vec<VR>,
75 edges_added: Vec<EA>,
76 edges_removed: Vec<ER>,
77 _phantom: std::marker::PhantomData<I>,
78}
79
80impl<VA, VR, EA, ER, I> Default for TwoPTwoPGraph<VA, VR, EA, ER, I>
81where
82 VA: Clone + TwoPTwoPAddVertex<I>,
83 VR: Clone + TwoPTwoPRemoveVertex<I>,
84 EA: Clone + TwoPTwoPAddEdge<I>,
85 ER: Clone + TwoPTwoPRemoveEdge<I>,
86 I: Eq + Hash + Debug + Clone,
87{
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl<VA, VR, EA, ER, I> TwoPTwoPGraph<VA, VR, EA, ER, I>
94where
95 VA: Clone + TwoPTwoPAddVertex<I>,
96 VR: Clone + TwoPTwoPRemoveVertex<I>,
97 EA: Clone + TwoPTwoPAddEdge<I>,
98 ER: Clone + TwoPTwoPRemoveEdge<I>,
99 I: Eq + Hash + Debug + Clone,
100{
101 pub fn new() -> Self {
103 TwoPTwoPGraph {
104 vertices_added: Vec::new(),
105 vertices_removed: Vec::new(),
106 edges_added: Vec::new(),
107 edges_removed: Vec::new(),
108 _phantom: std::marker::PhantomData,
109 }
110 }
111
112 pub fn lookup_vertex(&self, vertex_id: &I) -> bool {
114 self.vertices_added.iter().any(|va| va.id() == vertex_id)
115 && !self
116 .vertices_removed
117 .iter()
118 .any(|vr| vr.add_vertex_id() == vertex_id)
119 }
120
121 pub fn get_edge_added_from_remove_edge(&self, remove_edge: &ER) -> Option<&EA> {
123 self.edges_added
124 .iter()
125 .find(|ea| ea.id() == remove_edge.add_edge_id())
126 }
127
128 pub fn lookup_from_remove_edge(&self, remove_edge: &ER) -> bool {
131 self.get_edge_added_from_remove_edge(remove_edge)
132 .is_some_and(|edge_added| {
133 self.lookup_vertex(edge_added.source())
134 && self.lookup_vertex(edge_added.target())
135 && !self
136 .edges_removed
137 .iter()
138 .any(|er| er.add_edge_id() == remove_edge.add_edge_id())
139 })
140 }
141
142 pub fn update_operation(
144 &mut self,
145 update_operation: UpdateOperation<VA, VR, EA, ER>,
146 ) -> Result<(), TwoPTwoPGraphError<I>> {
147 self.prepare(update_operation).map(|_| ())
148 }
149
150 pub fn prepare(
153 &mut self,
154 op: UpdateOperation<VA, VR, EA, ER>,
155 ) -> Result<UpdateOperation<VA, VR, EA, ER>, TwoPTwoPGraphError<I>> {
156 let broadcast = op.clone();
157 match op {
158 UpdateOperation::AddVertex(vertex) => self.add_vertex(vertex, UpdateType::AtSource)?,
159 UpdateOperation::AddEdge(edge) => self.add_edge(edge, UpdateType::AtSource)?,
160 UpdateOperation::RemoveVertex(vertex) => {
161 self.remove_vertex(vertex, UpdateType::AtSource)?
162 }
163 UpdateOperation::RemoveEdge(edge) => self.remove_edge(edge, UpdateType::AtSource)?,
164 }
165 Ok(broadcast)
166 }
167
168 pub fn apply_downstream(
170 &mut self,
171 op: UpdateOperation<VA, VR, EA, ER>,
172 ) -> Result<(), TwoPTwoPGraphError<I>> {
173 match op {
174 UpdateOperation::AddVertex(vertex) => self.add_vertex(vertex, UpdateType::Downstream),
175 UpdateOperation::AddEdge(edge) => self.add_edge(edge, UpdateType::Downstream),
176 UpdateOperation::RemoveVertex(vertex) => {
177 self.remove_vertex(vertex, UpdateType::Downstream)
178 }
179 UpdateOperation::RemoveEdge(edge) => self.remove_edge(edge, UpdateType::Downstream),
180 }
181 }
182
183 pub fn add_vertex(
187 &mut self,
188 vertex: VA,
189 _update_type: UpdateType,
190 ) -> Result<(), TwoPTwoPGraphError<I>> {
191 if self.vertices_added.iter().any(|va| va.id() == vertex.id()) {
192 return Err(TwoPTwoPGraphError::VertexAlreadyExists(vertex.id().clone()));
193 }
194 self.vertices_added.push(vertex);
195 Ok(())
196 }
197
198 pub fn add_edge(
203 &mut self,
204 edge: EA,
205 update_type: UpdateType,
206 ) -> Result<(), TwoPTwoPGraphError<I>> {
207 if matches!(update_type, UpdateType::AtSource) {
208 if !self.lookup_vertex(&edge.source()) {
209 return Err(TwoPTwoPGraphError::VertexDoesNotExists(
210 edge.source().clone(),
211 ));
212 }
213 if !self.lookup_vertex(&edge.target()) {
214 return Err(TwoPTwoPGraphError::VertexDoesNotExists(
215 edge.target().clone(),
216 ));
217 }
218 }
219 if self.edges_added.iter().any(|ea| ea.id() == edge.id()) {
220 return Err(TwoPTwoPGraphError::EdgeAlreadyExists(edge.id().clone()));
221 }
222 self.edges_added.push(edge);
223 Ok(())
224 }
225
226 pub fn remove_vertex(
231 &mut self,
232 vertex: VR,
233 update_type: UpdateType,
234 ) -> Result<(), TwoPTwoPGraphError<I>> {
235 if matches!(update_type, UpdateType::AtSource) {
236 if !self.lookup_vertex(vertex.add_vertex_id()) {
238 return Err(TwoPTwoPGraphError::VertexDoesNotExists(
239 vertex.add_vertex_id().clone(),
240 ));
241 }
242 for ea in self.edges_added.iter() {
244 let is_removed = self
245 .edges_removed
246 .iter()
247 .any(|er| ea.id() == er.add_edge_id());
248 if !is_removed
249 && (ea.source() == vertex.add_vertex_id()
250 || ea.target() == vertex.add_vertex_id())
251 {
252 return Err(TwoPTwoPGraphError::VertexHasEdge(
253 vertex.add_vertex_id().clone(),
254 ea.id().clone(),
255 ));
256 }
257 }
258 }
259
260 if matches!(update_type, UpdateType::Downstream) {
261 if !self
263 .vertices_added
264 .iter()
265 .any(|va| va.id() == vertex.add_vertex_id())
266 {
267 return Err(TwoPTwoPGraphError::AddVertexNotDelivered(
268 vertex.add_vertex_id().clone(),
269 ));
270 }
271 }
272
273 if self
274 .vertices_removed
275 .iter()
276 .any(|vr| vr.id() == vertex.id())
277 {
278 return Err(TwoPTwoPGraphError::VertexAlreadyExists(vertex.id().clone()));
279 }
280 self.vertices_removed.push(vertex);
281 Ok(())
282 }
283
284 pub fn remove_edge(
289 &mut self,
290 remove_edge: ER,
291 update_type: UpdateType,
292 ) -> Result<(), TwoPTwoPGraphError<I>> {
293 if matches!(update_type, UpdateType::AtSource) {
294 if !self.lookup_from_remove_edge(&remove_edge) {
296 return Err(TwoPTwoPGraphError::EdgeDoesNotExists(
297 remove_edge.add_edge_id().clone(),
298 ));
299 }
300 }
301
302 if matches!(update_type, UpdateType::Downstream) {
303 if !self
305 .edges_added
306 .iter()
307 .any(|ea| ea.id() == remove_edge.add_edge_id())
308 {
309 return Err(TwoPTwoPGraphError::AddEdgeNotDelivered(
310 remove_edge.add_edge_id().clone(),
311 ));
312 }
313 }
314
315 if self
316 .edges_removed
317 .iter()
318 .any(|er| er.id() == remove_edge.id())
319 {
320 return Err(TwoPTwoPGraphError::EdgeAlreadyExists(
321 remove_edge.id().clone(),
322 ));
323 }
324 self.edges_removed.push(remove_edge);
325 Ok(())
326 }
327
328 pub fn generate_petgraph(&self) -> petgraph::graph::DiGraph<VA, EA> {
333 let mut graph = petgraph::graph::DiGraph::new();
334 let mut vertex_map = std::collections::HashMap::new();
335 for va in self.vertices_added.iter() {
336 let is_removed = self
337 .vertices_removed
338 .iter()
339 .any(|vr| va.id() == vr.add_vertex_id());
340 if !is_removed {
341 let vertex = graph.add_node(va.clone());
342 vertex_map.insert(va.id().clone(), vertex);
343 }
344 }
345 for ea in self.edges_added.iter() {
346 let is_removed = self
347 .edges_removed
348 .iter()
349 .any(|er| ea.id() == er.add_edge_id());
350 if !is_removed {
351 if let (Some(&source), Some(&target)) =
352 (vertex_map.get(ea.source()), vertex_map.get(ea.target()))
353 {
354 graph.add_edge(source, target, ea.clone());
355 }
356 }
357 }
358 graph
359 }
360
361 pub fn vertex_count(&self) -> usize {
363 self.vertices_added
364 .iter()
365 .filter(|va| {
366 !self
367 .vertices_removed
368 .iter()
369 .any(|vr| va.id() == vr.add_vertex_id())
370 })
371 .count()
372 }
373
374 pub fn edge_count(&self) -> usize {
376 self.edges_added
377 .iter()
378 .filter(|ea| {
379 !self
380 .edges_removed
381 .iter()
382 .any(|er| ea.id() == er.add_edge_id())
383 })
384 .count()
385 }
386
387 pub fn is_empty(&self) -> bool {
389 self.vertex_count() == 0 && self.edge_count() == 0
390 }
391
392 pub fn vertices(&self) -> impl Iterator<Item = &VA> {
394 self.vertices_added.iter().filter(|va| {
395 !self
396 .vertices_removed
397 .iter()
398 .any(|vr| va.id() == vr.add_vertex_id())
399 })
400 }
401
402 pub fn edges(&self) -> impl Iterator<Item = &EA> {
404 self.edges_added.iter().filter(|ea| {
405 !self
406 .edges_removed
407 .iter()
408 .any(|er| ea.id() == er.add_edge_id())
409 })
410 }
411}