graph_api_lib/walker/steps/
vertices.rs

1use crate::graph::Graph;
2use crate::search::vertex::VertexSearch;
3use crate::walker::builder::{StartWalkerBuilder, VertexWalkerBuilder};
4use crate::walker::steps::Empty;
5use crate::walker::{VertexWalker, Walker};
6use crate::{ElementId, VertexReference};
7use include_doc::function_body;
8use std::marker::PhantomData;
9// ================ VERTICES IMPLEMENTATION ================
10
11pub struct Vertices<'search, 'graph, Parent>
12where
13    Parent: VertexWalker<'graph>,
14    <Parent as Walker<'graph>>::Graph: 'graph,
15{
16    _phantom_data: PhantomData<&'graph ()>,
17    parent: Parent,
18    current_iter: Option<<Parent::Graph as Graph>::VertexIter<'search, 'graph>>,
19    vertex_search: VertexSearch<'search, Parent::Graph>,
20}
21
22impl<'search, 'graph, Parent> Vertices<'search, 'graph, Parent>
23where
24    Parent: VertexWalker<'graph>,
25    <Parent as Walker<'graph>>::Graph: 'graph,
26{
27    pub fn new(parent: Parent, vertex_search: VertexSearch<'search, Parent::Graph>) -> Self {
28        Self {
29            _phantom_data: Default::default(),
30            parent,
31            current_iter: None,
32            vertex_search,
33        }
34    }
35}
36
37impl<'graph, Parent> Walker<'graph> for Vertices<'_, 'graph, Parent>
38where
39    Parent: VertexWalker<'graph>,
40    <Parent as Walker<'graph>>::Graph: 'graph,
41{
42    type Graph = Parent::Graph;
43
44    type Context = Parent::Context;
45    fn next_element(&mut self, graph: &'graph Self::Graph) -> Option<ElementId<Self::Graph>> {
46        self.next(graph).map(ElementId::Vertex)
47    }
48    fn ctx(&self) -> &Parent::Context {
49        self.parent.ctx()
50    }
51    fn ctx_mut(&mut self) -> &mut Self::Context {
52        self.parent.ctx_mut()
53    }
54}
55
56impl<'graph, Parent> VertexWalker<'graph> for Vertices<'_, 'graph, Parent>
57where
58    Parent: VertexWalker<'graph>,
59    <Parent as Walker<'graph>>::Graph: 'graph,
60{
61    fn next(&mut self, graph: &'graph Self::Graph) -> Option<<Self::Graph as Graph>::VertexId> {
62        if self.current_iter.is_none() {
63            self.current_iter = Some(graph.vertices(&self.vertex_search));
64        }
65
66        self.current_iter
67            .as_mut()
68            .expect("iterator must be populated")
69            .next()
70            .map(|next| next.id())
71    }
72}
73
74impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
75where
76    Graph: crate::graph::Graph,
77    Walker: VertexWalker<'graph, Graph = Graph>,
78{
79    /// # Vertices Step
80    ///
81    /// The `vertices` step is the primary entry point for graph traversals, allowing you to select a set of
82    /// vertices to start traversing from. It accepts a `VertexSearch` parameter that specifies which
83    /// vertices to include in the traversal.
84    ///
85    /// ## Visual Diagram
86    ///
87    /// Before vertices step (empty traversal):
88    /// ```text
89    ///   [A] --- edge1 ---> [B] --- edge2 ---> [C]
90    ///    ^
91    ///    |
92    ///   edge3
93    ///    |
94    ///   [D]
95    /// ```
96    ///
97    /// After vertices step (with VertexSearch::scan()):
98    /// ```text
99    ///   [A]* --- edge1 ---> [B]* --- edge2 ---> [C]*
100    ///    ^
101    ///    |
102    ///   edge3
103    ///    |
104    ///   [D]*
105    /// ```
106    ///
107    /// After vertices step (with VertexSearch::scan().with_label(Vertex::person_label())):
108    /// ```text
109    ///   [Person A]* --- edge1 ---> [Project B]  --- edge2 ---> [Person C]*
110    ///    ^
111    ///    |
112    ///   edge3
113    ///    |
114    ///   [Person D]*
115    /// ```
116    ///
117    /// ## Parameters
118    ///
119    /// - `vertex_search`: A `VertexSearch` object that defines the criteria for selecting vertices
120    ///
121    /// ## Return Value
122    ///
123    /// Returns a traversal containing all vertices that match the search criteria.
124    ///
125    /// ## Example
126    ///
127    /// ```rust
128    #[doc = function_body!("examples/vertices.rs", example, [])]
129    /// ```
130    ///
131    /// For more examples, see the [vertices example](https://github.com/yourusername/graph-api/blob/main/graph-api-lib/examples/vertices.rs).
132    ///
133    /// ## Notes
134    ///
135    /// - The `vertices` step is typically the first step in a traversal
136    /// - Use `VertexIndex` methods for faster access when you have appropriate indexes defined
137    /// - For more complex criteria, you can chain the `filter` step after this one
138    /// - When working with large graphs, consider using indexed properties for better performance
139    /// - This step supports all vertex search mechanisms, including label-based, index-based, and full scans
140    /// - The traversal order is not guaranteed unless you specifically use an range index
141    pub fn vertices<'a, T: Into<VertexSearch<'a, Graph>>>(
142        self,
143        vertex_search: T,
144    ) -> VertexWalkerBuilder<'graph, Mutability, Graph, Vertices<'a, 'graph, Walker>> {
145        self.with_vertex_walker(|walker| walker.vertices(vertex_search.into()))
146    }
147}
148
149impl<'graph, Graph, Mutability, Context> StartWalkerBuilder<'graph, Mutability, Graph, Context>
150where
151    Graph: crate::graph::Graph,
152    Context: Clone + 'static,
153{
154    pub fn vertices<'search>(
155        self,
156        vertex_search: VertexSearch<'search, Graph>,
157    ) -> VertexWalkerBuilder<
158        'graph,
159        Mutability,
160        Graph,
161        Vertices<'search, 'graph, Empty<Graph, Context>>,
162    > {
163        crate::walker::builder::new(self.graph, self.empty.vertices(vertex_search))
164    }
165}