1use std::collections::HashSet;
14use std::sync::Arc;
15
16use crate::types::VertexId;
17use crate::vertex_edge_path::Step;
18use crate::{Edge, Path, Vertex};
19
20#[derive(Debug, Clone)]
25pub struct NPath {
26 parent: Option<Arc<NPath>>,
28 vertex: Arc<Vertex>,
30 edge: Option<Arc<Edge>>,
32 length: usize,
34 hash: u64,
36}
37
38impl NPath {
39 pub fn new(vertex: Arc<Vertex>) -> Self {
45 let hash = Self::compute_hash(&vertex, None, None);
46 Self {
47 parent: None,
48 vertex,
49 edge: None,
50 length: 0,
51 hash,
52 }
53 }
54
55 pub fn extend(parent: Arc<NPath>, edge: Arc<Edge>, vertex: Arc<Vertex>) -> Self {
65 let length = parent.length + 1;
66 let hash = Self::compute_hash(&vertex, Some(&edge), Some(parent.hash));
67 Self {
68 parent: Some(parent),
69 vertex,
70 edge: Some(edge),
71 length,
72 hash,
73 }
74 }
75
76 pub fn extend_with_set(
102 parent: Arc<NPath>,
103 edge: Arc<Edge>,
104 vertex: Arc<Vertex>,
105 seen_vertices: &mut HashSet<VertexId>,
106 ) -> Option<Self> {
107 if seen_vertices.contains(&vertex.vid) {
108 return None;
109 }
110
111 let new_path = Self::extend(parent, edge, vertex);
112 seen_vertices.insert(new_path.vertex.vid);
113 Some(new_path)
114 }
115
116 pub fn from_path(path: &Path) -> Arc<Self> {
130 let start_vertex = Arc::new((*path.src).clone());
131 let mut current = Arc::new(Self::new(start_vertex));
132
133 for step in &path.steps {
134 let edge = Arc::new((*step.edge).clone());
135 let vertex = Arc::new((*step.dst).clone());
136 current = Arc::new(Self::extend(current, edge, vertex));
137 }
138
139 current
140 }
141
142 pub fn len(&self) -> usize {
144 self.length
145 }
146
147 pub fn is_empty(&self) -> bool {
149 self.length == 0
150 }
151
152 pub fn vertex(&self) -> &Arc<Vertex> {
154 &self.vertex
155 }
156
157 pub fn edge(&self) -> Option<&Arc<Edge>> {
159 self.edge.as_ref()
160 }
161
162 pub fn parent(&self) -> Option<&Arc<NPath>> {
164 self.parent.as_ref()
165 }
166
167 pub fn start_vertex(&self) -> &Arc<Vertex> {
169 let mut current = self;
170 while let Some(ref parent) = current.parent {
171 current = parent;
172 }
173 ¤t.vertex
174 }
175
176 pub fn end_vertex(&self) -> &Arc<Vertex> {
178 &self.vertex
179 }
180
181 pub fn to_path(&self) -> Path {
185 let mut steps = Vec::with_capacity(self.length);
186 let mut current = self;
187
188 while let Some(ref parent) = current.parent {
190 if let Some(ref edge) = current.edge {
191 steps.push(Step {
192 dst: Box::new((*current.vertex).clone()),
193 edge: Box::new((**edge).clone()),
194 });
195 }
196 current = parent;
197 }
198
199 steps.reverse();
201
202 Path {
203 src: Box::new((*current.vertex).clone()),
204 steps,
205 }
206 }
207
208 pub fn contains_vertex(&self, vid: &VertexId) -> bool {
209 if &self.vertex.vid == vid {
210 return true;
211 }
212 if let Some(ref parent) = self.parent {
213 return parent.contains_vertex(vid);
214 }
215 false
216 }
217
218 pub fn contains_edge(&self, edge_key: &(VertexId, VertexId, String)) -> bool {
219 if let Some(ref edge) = self.edge {
220 let key = (edge.src, edge.dst, edge.edge_type.clone());
221 if &key == edge_key {
222 return true;
223 }
224 }
225 if let Some(ref parent) = self.parent {
226 return parent.contains_edge(edge_key);
227 }
228 false
229 }
230
231 pub fn has_common_vertices(&self, other: &NPath) -> bool {
232 let self_vertices: HashSet<_> = self.iter_vertices().map(|v| &v.vid).collect();
233 other
234 .iter_vertices()
235 .any(|v| self_vertices.contains(&v.vid))
236 }
237
238 pub fn collect_vertex_ids(&self) -> Vec<VertexId> {
239 self.iter_vertices().map(|v| v.vid).collect()
240 }
241
242 pub fn collect_edges(&self) -> Vec<Arc<Edge>> {
244 self.iter_edges().cloned().collect()
245 }
246
247 pub fn iter_vertices(&self) -> NPathVertexIter<'_> {
249 NPathVertexIter::new(self)
250 }
251
252 pub fn iter_edges(&self) -> NPathEdgeIter<'_> {
254 NPathEdgeIter::new(self)
255 }
256
257 pub fn iter(&self) -> NPathIter<'_> {
259 NPathIter::new(self)
260 }
261
262 fn compute_hash(
264 vertex: &Arc<Vertex>,
265 edge: Option<&Arc<Edge>>,
266 parent_hash: Option<u64>,
267 ) -> u64 {
268 use std::collections::hash_map::DefaultHasher;
269 use std::hash::{Hash, Hasher};
270
271 let mut hasher = DefaultHasher::new();
272
273 if let Some(ph) = parent_hash {
274 ph.hash(&mut hasher);
275 }
276
277 vertex.vid.hash(&mut hasher);
278
279 if let Some(e) = edge {
280 e.edge_type.hash(&mut hasher);
281 e.src.hash(&mut hasher);
282 e.dst.hash(&mut hasher);
283 }
284
285 hasher.finish()
286 }
287
288 pub fn hash(&self) -> u64 {
290 self.hash
291 }
292}
293
294impl PartialEq for NPath {
295 fn eq(&self, other: &Self) -> bool {
296 if self.hash != other.hash || self.length != other.length {
297 return false;
298 }
299
300 self.vertex.vid == other.vertex.vid
302 && self.edge == other.edge
303 && self.parent == other.parent
304 }
305}
306
307impl Eq for NPath {}
308
309pub struct NPathIter<'a> {
313 current: Option<&'a NPath>,
314}
315
316impl<'a> NPathIter<'a> {
317 fn new(path: &'a NPath) -> Self {
318 Self {
319 current: Some(path),
320 }
321 }
322}
323
324impl<'a> Iterator for NPathIter<'a> {
325 type Item = &'a NPath;
326
327 fn next(&mut self) -> Option<Self::Item> {
328 let curr = self.current?;
329 self.current = curr.parent.as_deref();
330 Some(curr)
331 }
332}
333
334pub struct NPathVertexIter<'a> {
338 current: Option<&'a NPath>,
339}
340
341impl<'a> NPathVertexIter<'a> {
342 fn new(path: &'a NPath) -> Self {
343 Self {
344 current: Some(path),
345 }
346 }
347}
348
349impl<'a> Iterator for NPathVertexIter<'a> {
350 type Item = &'a Arc<Vertex>;
351
352 fn next(&mut self) -> Option<Self::Item> {
353 let curr = self.current?;
354 let vertex = &curr.vertex;
355 self.current = curr.parent.as_deref();
356 Some(vertex)
357 }
358}
359
360pub struct NPathEdgeIter<'a> {
364 current: Option<&'a NPath>,
365}
366
367impl<'a> NPathEdgeIter<'a> {
368 fn new(path: &'a NPath) -> Self {
369 Self {
370 current: Some(path),
371 }
372 }
373}
374
375impl<'a> Iterator for NPathEdgeIter<'a> {
376 type Item = &'a Arc<Edge>;
377
378 fn next(&mut self) -> Option<Self::Item> {
379 let curr = self.current?;
380 let edge = curr.edge.as_ref()?;
381 self.current = curr.parent.as_deref();
382 Some(edge)
383 }
384}
385
386pub mod utils {
388 use super::*;
389
390 pub fn combine_paths(left: &Arc<NPath>, right: &Arc<NPath>) -> Option<Path> {
395 if left.vertex.vid != right.vertex.vid {
397 return None;
398 }
399
400 let left_path = left.to_path();
402
403 let mut right_path = right.to_path();
405 right_path.reverse();
406
407 let mut combined = left_path;
409 combined.steps.extend(right_path.steps);
410
411 Some(combined)
412 }
413
414 pub fn batch_to_paths(npaths: &[Arc<NPath>]) -> Vec<Path> {
416 npaths.iter().map(|np| np.to_path()).collect()
417 }
418
419 pub fn has_duplicates(npaths: &[Arc<NPath>]) -> bool {
421 let mut seen = HashSet::new();
422 for np in npaths {
423 if !seen.insert(np.hash()) {
424 return true;
425 }
426 }
427 false
428 }
429}
430
431#[cfg(test)]
432mod tests {
433 use super::*;
434 use crate::types::VertexId;
435 use crate::vertex_edge_path::Tag;
436 use std::collections::HashMap;
437
438 fn create_test_vertex(id: i64) -> Arc<Vertex> {
439 Arc::new(Vertex::new(
440 VertexId::try_from_int64(id).expect("test vertex id"),
441 Tag::new(String::new(), HashMap::new()),
442 ))
443 }
444
445 fn create_test_edge(src_id: i64, dst_id: i64, edge_type: &str) -> Arc<Edge> {
446 use std::collections::HashMap;
447 Arc::new(Edge::new(
448 VertexId::try_from_int64(src_id).expect("test vertex id"),
449 VertexId::try_from_int64(dst_id).expect("test vertex id"),
450 edge_type.to_string(),
451 0,
452 HashMap::new(),
453 ))
454 }
455
456 #[test]
457 fn test_npath_new() {
458 let v = create_test_vertex(1);
459 let path = NPath::new(v.clone());
460
461 assert_eq!(path.len(), 0);
462 assert!(path.is_empty());
463 assert_eq!(
464 path.vertex().vid,
465 VertexId::try_from_int64(1).expect("test vertex id")
466 );
467 assert!(path.parent().is_none());
468 assert!(path.edge().is_none());
469 }
470
471 #[test]
472 fn test_npath_extend() {
473 let v1 = create_test_vertex(1);
474 let v2 = create_test_vertex(2);
475 let e = create_test_edge(1, 2, "friend");
476
477 let start = Arc::new(NPath::new(v1));
478 let extended = NPath::extend(start, e, v2);
479
480 assert_eq!(extended.len(), 1);
481 assert!(!extended.is_empty());
482 assert_eq!(
483 extended.vertex().vid,
484 VertexId::try_from_int64(2).expect("test vertex id")
485 );
486 assert!(extended.parent().is_some());
487 assert!(extended.edge().is_some());
488 }
489
490 #[test]
491 fn test_npath_to_path() {
492 let v1 = create_test_vertex(1);
493 let v2 = create_test_vertex(2);
494 let v3 = create_test_vertex(3);
495 let e1 = create_test_edge(1, 2, "friend");
496 let e2 = create_test_edge(2, 3, "friend");
497
498 let start = Arc::new(NPath::new(v1));
499 let p2 = Arc::new(NPath::extend(start, e1, v2));
500 let p3 = Arc::new(NPath::extend(p2, e2, v3));
501
502 let path = p3.to_path();
503
504 assert_eq!(path.len(), 2);
505 assert_eq!(
506 path.src.vid,
507 VertexId::try_from_int64(1).expect("test vertex id")
508 );
509 }
510
511 #[test]
512 fn test_npath_contains_vertex() {
513 let v1 = create_test_vertex(1);
514 let v2 = create_test_vertex(2);
515 let v3 = create_test_vertex(3);
516 let e1 = create_test_edge(1, 2, "friend");
517 let e2 = create_test_edge(2, 3, "friend");
518
519 let start = Arc::new(NPath::new(v1));
520 let p2 = Arc::new(NPath::extend(start, e1, v2));
521 let p3 = Arc::new(NPath::extend(p2, e2, v3));
522
523 assert!(p3.contains_vertex(&VertexId::try_from_int64(1).expect("test vertex id")));
524 assert!(p3.contains_vertex(&VertexId::try_from_int64(2).expect("test vertex id")));
525 assert!(p3.contains_vertex(&VertexId::try_from_int64(3).expect("test vertex id")));
526 assert!(!p3.contains_vertex(&VertexId::try_from_int64(4).expect("test vertex id")));
527 }
528
529 #[test]
530 fn test_npath_iter_vertices() {
531 let v1 = create_test_vertex(1);
532 let v2 = create_test_vertex(2);
533 let v3 = create_test_vertex(3);
534 let e1 = create_test_edge(1, 2, "friend");
535 let e2 = create_test_edge(2, 3, "friend");
536
537 let start = Arc::new(NPath::new(v1));
538 let p2 = Arc::new(NPath::extend(start, e1, v2));
539 let p3 = Arc::new(NPath::extend(p2, e2, v3));
540
541 let vertices: Vec<_> = p3.iter_vertices().collect();
542 assert_eq!(vertices.len(), 3);
543 }
544
545 #[test]
546 fn test_npath_equality() {
547 let v1 = create_test_vertex(1);
548 let v2 = create_test_vertex(2);
549 let e = create_test_edge(1, 2, "friend");
550
551 let start1 = Arc::new(NPath::new(v1.clone()));
552 let path1 = Arc::new(NPath::extend(start1, e.clone(), v2.clone()));
553
554 let start2 = Arc::new(NPath::new(v1));
555 let path2 = Arc::new(NPath::extend(start2, e, v2));
556
557 assert_eq!(path1.hash(), path2.hash());
558 }
559}