1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use crate::graph::{EdgeReference, Graph};
use crate::walker::builder::{EdgeWalkerBuilder, VertexWalkerBuilder};
use crate::walker::{EdgeWalker, VertexWalker, Walker};
use crate::{EdgeSearch, ElementId};
use include_doc::function_body;
// ================ EDGES IMPLEMENTATION ================
pub struct Edges<'search, 'graph, Parent>
where
Parent: VertexWalker<'graph>,
<Parent as Walker<'graph>>::Graph: 'graph,
{
parent: Parent,
current_iter: Option<<Parent::Graph as Graph>::EdgeIter<'search, 'graph>>,
edge_search: EdgeSearch<'search, Parent::Graph>,
current: Option<<Parent::Graph as Graph>::VertexId>,
}
impl<'a, 'graph, Parent> Edges<'a, 'graph, Parent>
where
Parent: VertexWalker<'graph>,
{
pub(crate) fn new(
parent: Parent,
search: EdgeSearch<'a, Parent::Graph>,
) -> Edges<'a, 'graph, Parent> {
Self {
parent,
edge_search: search,
current_iter: None,
current: None,
}
}
}
impl<'search, 'graph, Parent> Walker<'graph> for Edges<'_, 'graph, Parent>
where
Parent: VertexWalker<'graph>,
<Parent as Walker<'graph>>::Graph: 'graph,
<Parent::Graph as Graph>::EdgeIter<'search, 'graph>:
Iterator<Item = <Parent::Graph as Graph>::EdgeReference<'graph>>,
{
type Graph = Parent::Graph;
type Context = Parent::Context;
fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
self.next(graph).map(ElementId::Edge)
}
fn ctx(&self) -> &Self::Context {
self.parent.ctx()
}
fn ctx_mut(&mut self) -> &mut Self::Context {
self.parent.ctx_mut()
}
}
impl<'graph, Parent> EdgeWalker<'graph> for Edges<'_, 'graph, Parent>
where
Parent: VertexWalker<'graph>,
<Parent as Walker<'graph>>::Graph: 'graph,
{
fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::EdgeId> {
loop {
if let Some(ref mut iter) = self.current_iter {
if let Some(edge) = iter.next() {
return Some(edge.id());
}
self.current_iter = None;
} else if let Some(vertex) = self.parent.next(graph) {
self.current = Some(vertex);
self.current_iter = Some(graph.edges(vertex, &self.edge_search));
} else {
return None;
}
}
}
}
impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
where
Graph: crate::graph::Graph,
Walker: VertexWalker<'graph, Graph = Graph>,
{
/// # Edges Step
///
/// The `edges` step allows you to traverse to the edges in a graph.
/// It moves the traversal position from vertices to their connected edges based on the provided search criteria.
///
/// ## Visual Diagram
///
/// Before edges step (traversal position on vertices):
/// ```text
/// [Person A]* --- knows ---> [Person B] --- created ---> [Project]
/// ^
/// |
/// owns
/// |
/// [Company C]
/// ```
///
/// After edges step with outgoing direction (traversal position moves to edges):
/// ```text
/// [Person A] --- knows --->* [Person B] --- created ---> [Project]
/// ^
/// |
/// owns -*
/// |
/// [Company C]
/// ```
///
/// ## Parameters
///
/// - `search`: An `EdgeSearch` that defines which edges to include. This can filter by label, direction, and other criteria.
///
/// ## Return Value
///
/// A new walker where the traversal position is on the edges matching the search criteria.
///
/// ## Example
///
/// ```rust
#[doc = function_body!("examples/edges.rs", example, [])]
/// ```
///
/// ## Notes
///
/// - The edges step changes the traversal position from vertices to edges
/// - To get back to vertices after an edges step, use `head()` or `tail()`
/// - The search direction matters: `.outgoing()` finds edges where the current vertex is the source,
/// `.incoming()` finds edges where the current vertex is the target, and `.bidirectional()` finds both
/// - The edges step can filter by label and other properties through the EdgeSearch parameter
pub fn edges<'a, T: Into<EdgeSearch<'a, Graph>>>(
self,
search: T,
) -> EdgeWalkerBuilder<'graph, Mutability, Graph, Edges<'a, 'graph, Walker>> {
self.with_edge_walker(|walker| walker.edges(search.into()))
}
}