graph_api_lib/walker/
builder.rs

1use crate::walker::steps::Empty;
2use crate::walker::{EdgeWalker, VertexWalker};
3use std::marker::PhantomData;
4
5/// A marker trait for types that can be mutated.
6///
7/// This trait is used to differentiate between mutable and immutable graph walkers.
8pub trait Mutable {}
9
10/// A marker type that indicates mutability.
11///
12/// Used as a type parameter in walker builders to enable mutable graph operations.
13pub struct MutableMarker;
14
15impl Mutable for MutableMarker {}
16
17/// A marker type that indicates immutability.
18///
19/// Used as a type parameter in walker builders to restrict operations to immutable ones.
20pub struct ImmutableMarker;
21
22/// Manages access to a graph during traversal operations.
23///
24/// This enum represents the three states of graph access:
25/// - Immutable: A shared reference to the graph
26/// - Mutable: An exclusive reference to the graph
27/// - Taken: The reference has been consumed
28#[derive(Default)]
29pub enum GraphAccess<'graph, Graph> {
30    /// A shared reference to a graph
31    Immutable(&'graph Graph),
32    /// An exclusive reference to a graph
33    Mutable(&'graph mut Graph),
34    /// The reference has been taken and can no longer be used
35    #[default]
36    Taken,
37}
38
39impl<'graph, Graph> GraphAccess<'graph, Graph> {
40    /// Takes the graph reference, leaving the enum in the `Taken` state.
41    ///
42    /// # Returns
43    /// A shared reference to the graph.
44    ///
45    /// # Panics
46    /// Panics if the graph reference has already been taken.
47    pub fn take(&mut self) -> &'graph Graph {
48        match std::mem::take(self) {
49            GraphAccess::Immutable(graph) => graph,
50            GraphAccess::Mutable(graph) => graph,
51            GraphAccess::Taken => panic!("graph already taken"),
52        }
53    }
54
55    /// Takes the graph reference for mutation, leaving the enum in the `Taken` state.
56    ///
57    /// # Returns
58    /// An exclusive reference to the graph.
59    ///
60    /// # Panics
61    /// Panics if the graph reference has already been taken or if it's an immutable reference.
62    pub fn take_mut(&mut self) -> &'graph mut Graph {
63        match std::mem::take(self) {
64            GraphAccess::Immutable(_) => {
65                panic!("graph should not have been accessed mutably")
66            }
67            GraphAccess::Mutable(graph) => graph,
68            GraphAccess::Taken => panic!("graph already taken"),
69        }
70    }
71}
72
73/// A generic builder for graph walkers.
74///
75/// This builder is used to construct and compose graph traversal operations.
76///
77/// # Type Parameters
78/// - `'graph`: The lifetime of the graph reference
79/// - `Mutability`: A marker type indicating whether graph mutations are allowed
80/// - `Graph`: The graph type being traversed
81/// - `Walker`: The walker implementation that will perform the traversal
82pub struct WalkerBuilder<'graph, Mutability, Graph, Walker>
83where
84    Walker: crate::walker::Walker<'graph>,
85{
86    pub(crate) _phantom: PhantomData<&'graph (Mutability, Graph, Walker)>,
87    pub(crate) walker: Walker,
88}
89
90impl<'graph, Mutability, Graph, Walker> WalkerBuilder<'graph, Mutability, Graph, Walker>
91where
92    Walker: crate::walker::Walker<'graph>,
93{
94    /// Returns a mutable reference to the underlying walker.
95    ///
96    /// This method provides access to the walker being built, allowing for direct manipulation.
97    ///
98    /// # Returns
99    /// A mutable reference to the walker.
100    pub fn walker(&mut self) -> &mut Walker {
101        &mut self.walker
102    }
103}
104
105impl<'graph, Mutability, Graph, Walker> From<VertexWalkerBuilder<'graph, Mutability, Graph, Walker>>
106    for WalkerBuilder<'graph, Mutability, Graph, Walker>
107where
108    Walker: VertexWalker<'graph, Graph = Graph>,
109{
110    fn from(value: VertexWalkerBuilder<'graph, Mutability, Graph, Walker>) -> Self {
111        WalkerBuilder {
112            _phantom: Default::default(),
113            walker: value.walker,
114        }
115    }
116}
117
118impl<'graph, Mutability, Graph, Walker> From<EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>>
119    for WalkerBuilder<'graph, Mutability, Graph, Walker>
120where
121    Walker: EdgeWalker<'graph, Graph = Graph>,
122{
123    fn from(value: EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>) -> Self {
124        WalkerBuilder {
125            _phantom: Default::default(),
126            walker: value.walker,
127        }
128    }
129}
130
131/// A builder for vertex-focused graph traversals.
132///
133/// This builder constructs walkers that navigate graphs by moving from vertex to vertex.
134///
135/// # Type Parameters
136/// - `'graph`: The lifetime of the graph reference
137/// - `Mutability`: A marker type indicating whether graph mutations are allowed
138/// - `Graph`: The graph type being traversed
139/// - `Walker`: The vertex walker implementation that will perform the traversal
140pub struct VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
141where
142    Walker: VertexWalker<'graph, Graph = Graph>,
143{
144    _phantom: PhantomData<&'graph Mutability>,
145    walker: Walker,
146    graph: GraphAccess<'graph, Graph>,
147}
148
149pub(crate) fn new<'graph, Mutability, Graph, Start>(
150    graph: GraphAccess<'graph, Graph>,
151    start: Start,
152) -> VertexWalkerBuilder<'graph, Mutability, Graph, Start>
153where
154    Graph: crate::graph::Graph,
155    Start: VertexWalker<'graph, Graph = Graph>,
156{
157    VertexWalkerBuilder {
158        _phantom: Default::default(),
159        walker: start,
160        graph,
161    }
162}
163
164#[allow(dead_code)]
165pub(crate) fn new_mut<'graph, Graph, Start>(
166    graph: &'graph mut Graph,
167    start: Start,
168) -> VertexWalkerBuilder<'graph, MutableMarker, Graph, Start>
169where
170    Graph: crate::graph::Graph,
171    Start: VertexWalker<'graph, Graph = Graph>,
172{
173    VertexWalkerBuilder {
174        _phantom: Default::default(),
175        walker: start,
176        graph: GraphAccess::Mutable(graph),
177    }
178}
179
180impl<'graph, Mutability, Graph, Walker> VertexWalkerBuilder<'graph, Mutability, Graph, Walker>
181where
182    Graph: crate::graph::Graph,
183    Walker: VertexWalker<'graph, Graph = Graph>,
184{
185    /// Returns an immutable reference to the graph being traversed.
186    ///
187    /// This consumes the graph reference, leaving the builder in a state
188    /// where the graph reference has been taken.
189    ///
190    /// # Returns
191    /// An immutable reference to the graph.
192    pub fn graph(&mut self) -> &'graph Graph {
193        self.graph.take()
194    }
195
196    /// Returns a mutable reference to the graph being traversed.
197    ///
198    /// This consumes the graph reference, leaving the builder in a state
199    /// where the graph reference has been taken.
200    ///
201    /// # Returns
202    /// A mutable reference to the graph.
203    ///
204    /// # Panics
205    /// Panics if the graph was not accessed mutably or has already been taken.
206    pub fn graph_mut(&mut self) -> &'graph mut Graph {
207        self.graph.take_mut()
208    }
209
210    /// Consumes the builder and returns the underlying walker.
211    ///
212    /// This extracts the walker from the builder, allowing it to be used directly.
213    ///
214    /// # Returns
215    /// The walker that was being built.
216    pub fn walker(self) -> Walker {
217        self.walker
218    }
219
220    /// Transforms the current vertex walker into an edge walker.
221    ///
222    /// This method allows for changing the traversal from vertex-oriented to edge-oriented
223    /// by applying a transformation function to the current walker.
224    ///
225    /// # Type Parameters
226    /// - `EdgeWalker`: The target edge walker type
227    /// - `WithFn`: A function type that converts the current walker to an edge walker
228    ///
229    /// # Parameters
230    /// - `step`: The transformation function to apply
231    ///
232    /// # Returns
233    /// A new edge walker builder containing the transformed walker
234    pub fn with_edge_walker<
235        EdgeWalker: crate::walker::EdgeWalker<'graph>,
236        WithFn: FnOnce(Walker) -> EdgeWalker,
237    >(
238        self,
239        step: WithFn,
240    ) -> EdgeWalkerBuilder<'graph, Mutability, Graph, EdgeWalker> {
241        EdgeWalkerBuilder {
242            _phantom: Default::default(),
243            walker: step(self.walker),
244            graph: self.graph,
245        }
246    }
247
248    /// Transforms the current vertex walker into another vertex walker.
249    ///
250    /// This method allows for changing or extending the traversal while remaining
251    /// vertex-oriented by applying a transformation function to the current walker.
252    ///
253    /// # Type Parameters
254    /// - `VertexWalker`: The target vertex walker type
255    /// - `WithFn`: A function type that converts the current walker to another vertex walker
256    ///
257    /// # Parameters
258    /// - `step`: The transformation function to apply
259    ///
260    /// # Returns
261    /// A new vertex walker builder containing the transformed walker
262    pub fn with_vertex_walker<
263        VertexWalker: crate::walker::VertexWalker<'graph, Graph = Graph>,
264        WithFn: FnOnce(Walker) -> VertexWalker,
265    >(
266        self,
267        step: WithFn,
268    ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexWalker> {
269        VertexWalkerBuilder {
270            _phantom: Default::default(),
271            walker: step(self.walker),
272            graph: self.graph,
273        }
274    }
275}
276
277/// A builder for edge-focused graph traversals.
278///
279/// This builder constructs walkers that navigate graphs by moving along edges.
280///
281/// # Type Parameters
282/// - `'graph`: The lifetime of the graph reference
283/// - `Mutability`: A marker type indicating whether graph mutations are allowed
284/// - `Graph`: The graph type being traversed
285/// - `Walker`: The edge walker implementation that will perform the traversal
286pub struct EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
287where
288    Walker: EdgeWalker<'graph>,
289{
290    _phantom: PhantomData<&'graph Mutability>,
291    walker: Walker,
292    graph: GraphAccess<'graph, Graph>,
293}
294
295impl<'graph, Mutability, Graph, Walker> EdgeWalkerBuilder<'graph, Mutability, Graph, Walker>
296where
297    Graph: crate::graph::Graph,
298    Walker: EdgeWalker<'graph, Graph = Graph>,
299    <Walker as crate::walker::Walker<'graph>>::Context: Clone + 'static,
300{
301    /// Returns an immutable reference to the graph being traversed.
302    ///
303    /// This consumes the graph reference, leaving the builder in a state
304    /// where the graph reference has been taken.
305    ///
306    /// # Returns
307    /// An immutable reference to the graph.
308    pub fn graph(&mut self) -> &'graph Graph {
309        self.graph.take()
310    }
311
312    /// Returns a mutable reference to the graph being traversed.
313    ///
314    /// This consumes the graph reference, leaving the builder in a state
315    /// where the graph reference has been taken.
316    ///
317    /// # Returns
318    /// A mutable reference to the graph.
319    ///
320    /// # Panics
321    /// Panics if the graph was not accessed mutably or has already been taken.
322    pub fn graph_mut(&mut self) -> &'graph mut Graph {
323        self.graph.take_mut()
324    }
325
326    /// Consumes the builder and returns the underlying walker.
327    ///
328    /// This extracts the walker from the builder, allowing it to be used directly.
329    ///
330    /// # Returns
331    /// The walker that was being built.
332    pub fn walker(self) -> Walker {
333        self.walker
334    }
335
336    /// Transforms the current walker into another edge walker.
337    ///
338    /// This method allows for changing or extending the traversal using
339    /// a transformation function applied to the current walker.
340    ///
341    /// # Type Parameters
342    /// - `EdgeWalker`: The target edge walker type
343    /// - `WithFn`: A function type that converts the current walker
344    ///
345    /// # Parameters
346    /// - `step`: The transformation function to apply
347    ///
348    /// # Returns
349    /// A new edge walker builder containing the transformed walker
350    pub fn with_edge_walker<
351        EdgeWalker: crate::walker::EdgeWalker<'graph>,
352        WithFn: FnOnce(Walker) -> EdgeWalker,
353    >(
354        self,
355        step: WithFn,
356    ) -> EdgeWalkerBuilder<'graph, Mutability, Graph, EdgeWalker> {
357        EdgeWalkerBuilder {
358            _phantom: Default::default(),
359            walker: step(self.walker),
360            graph: self.graph,
361        }
362    }
363
364    /// Transforms the current walker into a vertex walker.
365    ///
366    /// This method allows for changing the traversal from edge-oriented to vertex-oriented
367    /// by applying a transformation function to the current walker.
368    ///
369    /// # Type Parameters
370    /// - `VertexWalker`: The target vertex walker type
371    /// - `WithFn`: A function type that converts the current walker
372    ///
373    /// # Parameters
374    /// - `step`: The transformation function to apply
375    ///
376    /// # Returns
377    /// A new vertex walker builder containing the transformed walker
378    pub fn with_vertex_walker<
379        VertexWalker: crate::walker::VertexWalker<'graph, Graph = Graph>,
380        WithFn: FnOnce(Walker) -> VertexWalker,
381    >(
382        self,
383        step: WithFn,
384    ) -> VertexWalkerBuilder<'graph, Mutability, Graph, VertexWalker> {
385        VertexWalkerBuilder {
386            _phantom: Default::default(),
387            walker: step(self.walker),
388            graph: self.graph,
389        }
390    }
391}
392
393pub(crate) fn new_start<Graph>(graph: &Graph) -> StartWalkerBuilder<'_, ImmutableMarker, Graph, ()>
394where
395    Graph: crate::graph::Graph,
396{
397    StartWalkerBuilder {
398        _phantom: Default::default(),
399        graph: GraphAccess::Immutable(graph),
400        empty: Empty::default(),
401    }
402}
403
404pub(crate) fn new_start_mut<Graph>(
405    graph: &mut Graph,
406) -> StartWalkerBuilder<'_, MutableMarker, Graph, ()>
407where
408    Graph: crate::graph::Graph,
409{
410    StartWalkerBuilder {
411        _phantom: Default::default(),
412        graph: GraphAccess::Mutable(graph),
413        empty: Empty::default(),
414    }
415}
416
417/// The initial builder for starting a graph traversal.
418///
419/// This builder is the entry point for creating graph traversals. It contains
420/// a reference to the graph and an empty context, and provides methods to begin
421/// traversing the graph.
422///
423/// # Type Parameters
424/// - `'graph`: The lifetime of the graph reference
425/// - `Mutability`: A marker type indicating whether graph mutations are allowed
426/// - `Graph`: The graph type being traversed
427/// - `Context`: The initial context type for the traversal
428pub struct StartWalkerBuilder<'graph, Mutability, Graph, Context> {
429    pub(crate) _phantom: PhantomData<&'graph (Mutability, Graph)>,
430    pub(crate) graph: GraphAccess<'graph, Graph>,
431    pub(crate) empty: Empty<Graph, Context>,
432}