guppy/petgraph_support/
walk.rs
1use crate::petgraph_support::edge_triple;
5use petgraph::visit::{IntoEdges, VisitMap, Visitable, Walker};
6use std::iter;
7
8#[derive(Clone, Debug)]
9pub(crate) struct EdgeDfs<E, N, VM> {
10 pub stack: Vec<(N, N, E)>,
12 pub discovered: VM,
14}
15
16impl<E, N, VM> EdgeDfs<E, N, VM>
17where
18 E: Copy + PartialEq,
19 N: Copy + PartialEq,
20 VM: VisitMap<N>,
21{
22 pub(crate) fn new<G>(graph: G, initials: impl IntoIterator<Item = N>) -> Self
25 where
26 G: Visitable<Map = VM> + IntoEdges<NodeId = N, EdgeId = E>,
27 {
28 let mut discovered = graph.visit_map();
29 let stack = initials
30 .into_iter()
31 .filter_map(|node_ix| {
32 if discovered.visit(node_ix) {
35 Some(graph.edges(node_ix).map(edge_triple))
36 } else {
37 None
38 }
39 })
40 .flatten()
41 .collect();
42 Self { stack, discovered }
43 }
44
45 #[allow(dead_code)]
48 pub(crate) fn new_single<G>(graph: G, start: N) -> Self
49 where
50 G: Visitable<Map = VM> + IntoEdges<NodeId = N, EdgeId = E>,
51 {
52 Self::new(graph, iter::once(start))
53 }
54
55 pub fn next<G>(&mut self, graph: G) -> Option<(N, N, E)>
57 where
58 G: IntoEdges<NodeId = N, EdgeId = E>,
59 {
60 let (source, target, edge) = self.stack.pop()?;
61 if self.discovered.visit(target) {
62 self.stack.extend(graph.edges(target).map(edge_triple));
63 }
64 Some((source, target, edge))
65 }
66}
67
68impl<G> Walker<G> for EdgeDfs<G::EdgeId, G::NodeId, G::Map>
69where
70 G: IntoEdges + Visitable,
71{
72 type Item = (G::NodeId, G::NodeId, G::EdgeId);
73
74 fn walk_next(&mut self, context: G) -> Option<Self::Item> {
75 self.next(context)
76 }
77}