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}