daggy/
walker.rs

1//! **Walker** is a trait providing a variety of useful methods for traversing graph types.
2
3use petgraph::visit::{GraphBase, GraphRef, Walker};
4use std::marker::PhantomData;
5
6/// Recursively walks a graph using the recursive function `recursive_fn`.
7#[derive(Clone, Debug)]
8pub struct Recursive<G, F>
9where
10    G: GraphBase,
11{
12    next: G::NodeId,
13    recursive_fn: F,
14    _graph: PhantomData<G>,
15}
16
17impl<G, F> Recursive<G, F>
18where
19    G: GraphBase,
20    F: FnMut(&G, G::NodeId) -> Option<(G::EdgeId, G::NodeId)>,
21{
22    /// Construct a new **Recursive** **Walker** starting from the node at the given index.
23    pub fn new(start: G::NodeId, recursive_fn: F) -> Self {
24        Recursive {
25            next: start,
26            recursive_fn: recursive_fn,
27            _graph: PhantomData,
28        }
29    }
30
31    /// Yield the next recursion step.
32    pub fn next(&mut self, g: &G) -> Option<(G::EdgeId, G::NodeId)> {
33        let Recursive {
34            ref mut next,
35            ref mut recursive_fn,
36            ..
37        } = *self;
38        recursive_fn(g, *next).map(|(e, n)| {
39            *next = n;
40            (e, n)
41        })
42    }
43}
44
45impl<'a, G, F> Walker<&'a G> for Recursive<G, F>
46where
47    G: GraphBase,
48    F: FnMut(&G, G::NodeId) -> Option<(G::EdgeId, G::NodeId)>,
49{
50    type Item = (G::EdgeId, G::NodeId);
51    #[inline]
52    fn walk_next(&mut self, g: &G) -> Option<Self::Item> {
53        self.next(g)
54    }
55}
56
57/// Walks the entirety of `a` before walking the entirety of `b`.
58#[derive(Clone, Debug)]
59pub struct Chain<G, A, B> {
60    a: Option<A>,
61    b: B,
62    _graph: PhantomData<G>,
63}
64
65impl<G, A, B> Chain<G, A, B> {
66    /// Create a new `Chain`.
67    pub fn new(a: A, b: B) -> Self {
68        Chain {
69            a: Some(a),
70            b,
71            _graph: PhantomData,
72        }
73    }
74}
75
76impl<'a, G, A, B> Walker<&'a G> for Chain<G, A, B>
77where
78    G: GraphBase,
79    A: Walker<&'a G>,
80    B: Walker<&'a G, Item = A::Item>,
81{
82    type Item = A::Item;
83    #[inline]
84    fn walk_next(&mut self, graph: &'a G) -> Option<Self::Item> {
85        let Chain {
86            ref mut a,
87            ref mut b,
88            ..
89        } = *self;
90        match a.as_mut().and_then(|walker| walker.walk_next(graph)) {
91            Some(step) => Some(step),
92            None => {
93                *a = None;
94                b.walk_next(graph)
95            }
96        }
97    }
98}
99
100/// A walker that applies some given predicate to each element returned by its walker.
101///
102/// The only index pairs that will be yielded are those that make the predicate evaluate to true.
103#[derive(Clone, Debug)]
104pub struct Filter<G, W, P> {
105    walker: W,
106    predicate: P,
107    _graph: PhantomData<G>,
108}
109
110impl<G, W, P> Filter<G, W, P> {
111    /// Create a new `Filter`.
112    pub fn new(walker: W, predicate: P) -> Self
113    where
114        G: GraphRef,
115        W: Walker<G>,
116        P: FnMut(G, &W::Item) -> bool,
117    {
118        Filter {
119            walker,
120            predicate,
121            _graph: PhantomData,
122        }
123    }
124}
125
126impl<G, W, P> Walker<G> for Filter<G, W, P>
127where
128    G: GraphRef,
129    W: Walker<G>,
130    P: FnMut(G, &W::Item) -> bool,
131{
132    type Item = W::Item;
133    #[inline]
134    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
135        while let Some(item) = self.walker.walk_next(graph) {
136            if (self.predicate)(graph, &item) {
137                return Some(item);
138            }
139        }
140        None
141    }
142}
143
144/// A walker that has a `.peek(&graph)` method that returns an optional next neighbor.
145#[derive(Clone, Debug)]
146pub struct Peekable<G, W>
147where
148    W: Walker<G>,
149{
150    walker: W,
151    maybe_next: Option<W::Item>,
152    _graph: PhantomData<G>,
153}
154
155impl<G, W> Peekable<G, W>
156where
157    G: GraphRef,
158    W: Walker<G>,
159{
160    /// Create a new `Peekable` walker.
161    pub fn new(walker: W) -> Self {
162        Peekable {
163            walker,
164            maybe_next: None,
165            _graph: PhantomData,
166        }
167    }
168
169    /// The edge node index pair of the neighbor at the next step in our walk of the given graph.
170    #[inline]
171    pub fn peek(&mut self, graph: G) -> Option<&W::Item> {
172        if self.maybe_next.is_none() {
173            self.maybe_next = self.walker.walk_next(graph);
174        }
175        self.maybe_next.as_ref()
176    }
177}
178
179impl<G, W> Walker<G> for Peekable<G, W>
180where
181    G: GraphRef,
182    W: Walker<G>,
183{
184    type Item = W::Item;
185    #[inline]
186    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
187        self.maybe_next
188            .take()
189            .or_else(|| self.walker.walk_next(graph))
190    }
191}
192
193/// A walker that invokes the predicate on elements until it returns false.
194///
195/// Once the predicate returns false, that element and all further elements are yielded.
196#[derive(Clone, Debug)]
197pub struct SkipWhile<G, W, P> {
198    walker: W,
199    maybe_predicate: Option<P>,
200    _graph: PhantomData<G>,
201}
202
203impl<G, W, P> SkipWhile<G, W, P> {
204    /// Create a new `SkipWhile` walker.
205    pub fn new(walker: W, predicate: P) -> Self
206    where
207        G: GraphRef,
208        W: Walker<G>,
209        P: FnMut(G, &W::Item) -> bool,
210    {
211        SkipWhile {
212            walker,
213            maybe_predicate: Some(predicate),
214            _graph: PhantomData,
215        }
216    }
217}
218
219impl<G, W, P> Walker<G> for SkipWhile<G, W, P>
220where
221    G: GraphRef,
222    W: Walker<G>,
223    P: FnMut(G, &W::Item) -> bool,
224{
225    type Item = W::Item;
226    #[inline]
227    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
228        match self.maybe_predicate.take() {
229            Some(mut predicate) => {
230                while let Some(item) = self.walker.walk_next(graph) {
231                    if !predicate(graph, &item) {
232                        return Some(item);
233                    }
234                }
235                None
236            }
237            None => self.walker.walk_next(graph),
238        }
239    }
240}
241
242/// A walker that yields elements so long as the predicate returns true.
243///
244/// After the predicate returns false for the first time, no further elements will be yielded.
245#[derive(Clone, Debug)]
246pub struct TakeWhile<G, W, P> {
247    maybe_walker: Option<W>,
248    predicate: P,
249    _graph: PhantomData<G>,
250}
251
252impl<G, W, P> TakeWhile<G, W, P> {
253    /// Create a new `TakeWhile` walker.
254    pub fn new(walker: W, predicate: P) -> Self
255    where
256        G: GraphRef,
257        W: Walker<G>,
258        P: FnMut(G, &W::Item) -> bool,
259    {
260        TakeWhile {
261            maybe_walker: Some(walker),
262            predicate,
263            _graph: PhantomData,
264        }
265    }
266}
267
268impl<G, W, P> Walker<G> for TakeWhile<G, W, P>
269where
270    G: GraphRef,
271    W: Walker<G>,
272    P: FnMut(G, &W::Item) -> bool,
273{
274    type Item = W::Item;
275    #[inline]
276    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
277        let TakeWhile {
278            ref mut maybe_walker,
279            ref mut predicate,
280            ..
281        } = *self;
282        let maybe_next_idx_pair = maybe_walker
283            .as_mut()
284            .and_then(|walker| walker.walk_next(graph));
285        if let Some(item) = maybe_next_idx_pair {
286            if predicate(graph, &item) {
287                return Some(item);
288            } else {
289                *maybe_walker = None;
290            }
291        }
292        None
293    }
294}
295
296/// A walker that skips the first n steps of this walk, and then yields all further steps.
297#[derive(Clone, Debug)]
298pub struct Skip<G, W> {
299    walker: W,
300    to_skip: usize,
301    _graph: PhantomData<G>,
302}
303
304impl<G, W> Skip<G, W> {
305    /// Create a new `Skip` walker..
306    pub fn new(walker: W, to_skip: usize) -> Self {
307        Skip {
308            walker,
309            to_skip,
310            _graph: PhantomData,
311        }
312    }
313}
314
315impl<G, W> Walker<G> for Skip<G, W>
316where
317    G: GraphRef,
318    W: Walker<G>,
319{
320    type Item = W::Item;
321    #[inline]
322    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
323        if self.to_skip > 0 {
324            for _ in 0..self.to_skip {
325                self.walker.walk_next(graph);
326            }
327            self.to_skip = 0;
328        }
329        self.walker.walk_next(graph)
330    }
331}
332
333/// A walker that yields the first n steps of this walk.
334#[derive(Clone, Debug)]
335pub struct Take<G, W> {
336    walker: W,
337    to_take: usize,
338    _graph: PhantomData<G>,
339}
340
341impl<G, W> Take<G, W> {
342    /// Create a new `Take` walker.
343    pub fn new(walker: W, to_take: usize) -> Self {
344        Take {
345            walker,
346            to_take,
347            _graph: PhantomData,
348        }
349    }
350}
351
352impl<G, W> Walker<G> for Take<G, W>
353where
354    G: GraphRef,
355    W: Walker<G>,
356{
357    type Item = W::Item;
358    #[inline]
359    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
360        if self.to_take > 0 {
361            self.to_take -= 1;
362            self.walker.walk_next(graph)
363        } else {
364            None
365        }
366    }
367}
368
369/// A walker that repeats its internal walker endlessly.
370#[derive(Clone, Debug)]
371pub struct Cycle<G, W> {
372    walker: W,
373    clone: W,
374    _graph: PhantomData<G>,
375}
376
377impl<G, W> Cycle<G, W>
378where
379    W: Clone,
380{
381    /// Create a new `Cycle` walker.
382    pub fn new(walker: W) -> Self {
383        let clone = walker.clone();
384        Cycle {
385            walker,
386            clone,
387            _graph: PhantomData,
388        }
389    }
390}
391
392impl<G, W> Walker<G> for Cycle<G, W>
393where
394    G: GraphRef,
395    W: Walker<G> + Clone,
396{
397    type Item = W::Item;
398    #[inline]
399    fn walk_next(&mut self, graph: G) -> Option<Self::Item> {
400        self.clone.walk_next(graph).or_else(|| {
401            self.clone = self.walker.clone();
402            self.clone.walk_next(graph)
403        })
404    }
405}
406
407/// A walker that calls a function with a reference to each index pair before yielding them.
408///
409/// This is often useful for debugging a walker pipeline.
410#[derive(Clone, Debug)]
411pub struct Inspect<W, F> {
412    walker: W,
413    f: F,
414}
415
416impl<W, F> Inspect<W, F> {
417    /// Create a new `Inspect` walker.
418    pub fn new(walker: W, f: F) -> Self {
419        Inspect { walker, f }
420    }
421}
422
423impl<G, W, F> Walker<G> for Inspect<W, F>
424where
425    G: GraphRef,
426    W: Walker<G>,
427    F: FnMut(G, &W::Item),
428{
429    type Item = W::Item;
430    #[inline]
431    fn walk_next(&mut self, graph: G) -> Option<W::Item> {
432        self.walker.walk_next(graph).map(|item| {
433            (self.f)(graph, &item);
434            item
435        })
436    }
437}