graph_api_lib/walker/steps/
into_iter.rs

1use crate::walker::builder::{EdgeWalkerBuilder, VertexWalkerBuilder};
2use crate::walker::{EdgeWalker, VertexWalker};
3use include_doc::function_body;
4
5/// # Iter Step
6///
7/// While there is no explicit `iter` step method in the walker API, the walker builders implement
8/// the `IntoIterator` trait, allowing you to convert a traversal into a standard Rust iterator
9/// with the `.into_iter()` method. This enables using standard iterator methods like `map`,
10/// `filter`, and `fold` on your graph traversal results.
11///
12/// ## Visual Diagram
13///
14/// Before iter (walker traversal):
15/// ```text
16///   [A]* --- edge1 ---> [B]* --- edge2 ---> [C]*  
17///    ^                                         
18///    |                                         
19///   edge3                                       
20///    |                                         
21///   [D]*                                        
22/// ```
23///
24/// After iter (converted to standard Rust iterator):
25/// ```text
26///   Iterator<Item = VertexId>  or  Iterator<Item = EdgeId>
27///   A -> B -> C -> D
28/// ```
29///
30/// When using `map()`, the iterator yields references with contexts:
31/// ```text
32///   Iterator<Item = (reference, context)>
33///   [A, ctx] -> [B, ctx] -> [C, ctx] -> [D, ctx]
34/// ```
35///
36/// ## Parameters
37///
38/// None (when using `.into_iter()`)
39///
40/// ## Return Value
41///
42/// An iterator that yields element IDs (vertex or edge IDs, depending on the walker type).
43///
44/// When using the `map()` method, the iterator yields tuples of `(reference, context)` where:
45/// - `reference` is either a vertex or edge reference depending on the walker type
46/// - `context` contains any accumulated context data from the traversal
47///
48/// ## Example
49///
50/// ```rust
51#[doc = function_body!("examples/into_iter.rs", example, [])]
52/// ```
53///
54/// For more examples, see the [into_iter example](https://github.com/yourusername/graph-api/blob/main/graph-api-lib/examples/into_iter.rs).
55///
56/// ## Notes
57///
58/// - Using `.into_iter()` consumes the walker and returns an iterator over element IDs
59/// - This is the bridge between Graph API's walker system and Rust's standard iterator ecosystem
60/// - After converting to an iterator, you can use all standard Rust iterator methods
61/// - Prefer using walker steps for graph traversal logic, and iterator methods for post-traversal processing
62impl<'graph, Mutability, Graph, Walker> IntoIterator
63    for VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
64where
65    Graph: crate::graph::Graph,
66    Walker: VertexWalker<'graph, Graph = Graph>,
67{
68    type Item = Graph::VertexId;
69    type IntoIter = VertexIterImpl<'graph, Graph, Walker>;
70
71    fn into_iter(mut self) -> Self::IntoIter {
72        VertexIterImpl::new(self.graph(), self.walker())
73    }
74}
75
76impl<'graph, Mutability, Graph, Walker> IntoIterator
77    for EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
78where
79    Graph: crate::graph::Graph,
80    Walker: EdgeWalker<'graph, Graph = Graph>,
81{
82    type Item = Graph::EdgeId;
83    type IntoIter = EdgeIterImpl<'graph, Graph, Walker>;
84
85    fn into_iter(mut self) -> Self::IntoIter {
86        EdgeIterImpl::new(self.graph(), self.walker())
87    }
88}
89
90pub struct VertexReferenceIterImpl<'graph, Graph, Walker> {
91    graph: &'graph Graph,
92    walker: Walker,
93}
94
95impl<'graph, Graph, Walker> VertexReferenceIterImpl<'graph, Graph, Walker> {
96    pub(crate) fn new(graph: &'graph Graph, walker: Walker) -> Self
97    where
98        Graph: crate::graph::Graph,
99        Walker: VertexWalker<'graph, Graph = Graph>,
100    {
101        Self { graph, walker }
102    }
103}
104
105impl<'graph, Graph, Walker> Iterator for VertexReferenceIterImpl<'graph, Graph, Walker>
106where
107    Graph: crate::graph::Graph,
108    Walker: VertexWalker<'graph, Graph = Graph>,
109{
110    type Item = (Graph::VertexReference<'graph>, Walker::Context);
111
112    fn next(&mut self) -> Option<Self::Item> {
113        if let Some(next) = self.walker.next(self.graph) {
114            Some((
115                self.graph
116                    .vertex(next)
117                    .expect("vertex ID must resolve to vertex"),
118                self.walker.ctx().clone(),
119            ))
120        } else {
121            None
122        }
123    }
124}
125
126pub struct EdgeReferenceIterImpl<'graph, Graph, Walker> {
127    graph: &'graph Graph,
128    walker: Walker,
129}
130
131impl<'graph, Graph, Walker> EdgeReferenceIterImpl<'graph, Graph, Walker> {
132    pub(crate) fn new(graph: &'graph Graph, walker: Walker) -> Self
133    where
134        Graph: crate::graph::Graph,
135        Walker: EdgeWalker<'graph, Graph = Graph>,
136    {
137        Self { graph, walker }
138    }
139}
140
141impl<'graph, Graph, Walker> Iterator for EdgeReferenceIterImpl<'graph, Graph, Walker>
142where
143    Graph: crate::graph::Graph,
144    Walker: EdgeWalker<'graph, Graph = Graph>,
145{
146    type Item = (Graph::EdgeReference<'graph>, Walker::Context);
147
148    fn next(&mut self) -> Option<Self::Item> {
149        if let Some(next) = self.walker.next(self.graph) {
150            let edge = self
151                .graph
152                .edge(next)
153                .expect("edge ID must resolve to an edge");
154            Some((edge, self.walker.ctx().clone()))
155        } else {
156            None
157        }
158    }
159}
160
161pub struct VertexIterImpl<'graph, Graph, Walker> {
162    graph: &'graph Graph,
163    walker: Walker,
164}
165
166impl<'graph, Graph, Walker> VertexIterImpl<'graph, Graph, Walker> {
167    pub(crate) fn new(graph: &'graph Graph, walker: Walker) -> Self
168    where
169        Graph: crate::graph::Graph,
170        Walker: VertexWalker<'graph, Graph = Graph>,
171    {
172        Self { graph, walker }
173    }
174}
175
176impl<'graph, Graph, Walker> Iterator for VertexIterImpl<'graph, Graph, Walker>
177where
178    Graph: crate::graph::Graph,
179    Walker: VertexWalker<'graph, Graph = Graph>,
180{
181    type Item = Graph::VertexId;
182
183    fn next(&mut self) -> Option<Self::Item> {
184        self.walker.next(self.graph)
185    }
186}
187
188pub struct EdgeIterImpl<'graph, Graph, Walker> {
189    graph: &'graph Graph,
190    walker: Walker,
191}
192
193impl<'graph, Graph, Walker> EdgeIterImpl<'graph, Graph, Walker> {
194    pub(crate) fn new(graph: &'graph Graph, walker: Walker) -> Self
195    where
196        Graph: crate::graph::Graph,
197        Walker: EdgeWalker<'graph, Graph = Graph>,
198    {
199        Self { graph, walker }
200    }
201}
202
203impl<'graph, Graph, Walker> Iterator for EdgeIterImpl<'graph, Graph, Walker>
204where
205    Graph: crate::graph::Graph,
206    Walker: EdgeWalker<'graph, Graph = Graph>,
207{
208    type Item = Graph::EdgeId;
209
210    fn next(&mut self) -> Option<Self::Item> {
211        self.walker.next(self.graph)
212    }
213}