graph_api_lib/walker/steps/mutate.rs
1use crate::walker::builder::{EdgeWalkerBuilder, Mutable, VertexWalkerBuilder};
2use crate::walker::{EdgeWalker, VertexWalker};
3use include_doc::function_body;
4
5impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
6where
7 Graph: crate::graph::Graph,
8 Walker: VertexWalker<'graph, Graph = Graph>,
9{
10 /// # Mutate Step
11 ///
12 /// The `mutate` step allows you to modify the graph during traversal. For each element
13 /// in the traversal (vertex or edge), the provided callback function is executed, giving
14 /// you the ability to create, modify, or delete elements in the graph.
15 ///
16 /// ## Visual Diagram
17 ///
18 /// Before mutate step (traversal position on Person vertices):
19 /// ```text
20 /// [Person A]* [Project X]
21 /// |
22 /// [Person B]*
23 /// ```
24 ///
25 /// After mutate step (adding 'Created' edges to Project X):
26 /// ```text
27 /// [Person A]* ---- Created ----> [Project X]
28 /// |
29 /// [Person B]* ---- Created ----> [Project X]
30 /// ```
31 ///
32 /// ## Parameters
33 ///
34 /// - `callback`: A function that receives:
35 /// - A mutable reference to the graph
36 /// - The element ID (vertex ID or edge ID)
37 /// - The context for the current element
38 ///
39 /// ## Requirements
40 ///
41 /// - Must use `walk_mut()` instead of `walk()` to get a mutable graph reference
42 /// - Works with both vertex and edge traversals
43 /// - The traversal is collected before mutations are applied to avoid interference
44 ///
45 /// ## Return Value
46 ///
47 /// Returns the number of elements that were modified (traversed and passed to the callback).
48 ///
49 /// ## Example
50 ///
51 /// ```rust
52 #[doc = function_body!("examples/mutate.rs", basic_example, [])]
53 /// ```
54 ///
55 /// ## Notes
56 ///
57 /// - The `mutate` step doesn't change the traversal position or context
58 /// - All modifications happen to the graph itself, not to the traversal
59 /// - The traversal is completed first, then mutations are applied afterward to avoid traversal interference
60 /// - Be cautious when performing mutations that might interact with each other
61 /// - For better performance with large traversals, consider using `limit()` before `mutate()`
62 /// - Can be used to implement complex graph algorithms like community detection, path finding, or graph rewriting
63 /// - Related steps: `filter()` for conditional traversal, `collect()` for materializing results
64 pub fn mutate<Callback>(mut self, callback: Callback) -> usize
65 where
66 Callback: Fn(&mut Walker::Graph, Graph::VertexId, &Walker::Context),
67 Mutability: Mutable,
68 'graph: 'graph,
69 {
70 let graph = self.graph_mut();
71 let graph_copy: &Graph = unsafe { std::mem::transmute(&*graph) };
72 let mut walker = self.walker();
73
74 let mut contexts = Vec::new();
75 while let Some(vertex_id) = walker.next(graph_copy) {
76 let ctx = walker.ctx().clone();
77 contexts.push((vertex_id, ctx));
78 }
79
80 let mut count = 0;
81 for (vertex_id, ctx) in contexts {
82 callback(graph, vertex_id, &ctx);
83 count += 1;
84 }
85 count
86 }
87}
88
89impl<'graph, Mutability, Graph, Walker> EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
90where
91 Graph: crate::graph::Graph,
92 Walker: EdgeWalker<'graph, Graph = Graph>,
93{
94 /// # Mutate Step
95 ///
96 /// Allows you to modify the graph during edge traversal.
97 ///
98 /// See the documentation for [`VertexWalkerBuilder::mutate`] for more details.
99 pub fn mutate<Callback>(mut self, callback: Callback) -> usize
100 where
101 Callback: Fn(&mut Walker::Graph, Graph::EdgeId, &Walker::Context),
102 Mutability: Mutable,
103 'graph: 'graph,
104 {
105 let graph = self.graph_mut();
106 let graph_copy: &Graph = unsafe { std::mem::transmute(&*graph) };
107 let mut walker = self.walker();
108
109 let mut contexts = Vec::new();
110 while let Some(edge) = walker.next(graph_copy) {
111 let ctx = walker.ctx().clone();
112 contexts.push((edge, ctx));
113 }
114
115 let mut count = 0;
116 for (edge_id, ctx) in contexts {
117 callback(graph, edge_id, &ctx);
118 count += 1;
119 }
120 count
121 }
122}