petgraph/visit/
undirected_adaptor.rs1use crate::visit::{
2 Data, GraphBase, GraphProp, GraphRef, IntoEdgeReferences, IntoEdges, IntoEdgesDirected,
3 IntoNeighbors, IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences,
4 NodeCompactIndexable, NodeCount, NodeIndexable, Visitable,
5};
6use crate::Direction;
7
8#[derive(Copy, Clone, Debug)]
10pub struct UndirectedAdaptor<G>(pub G);
11
12impl<G: GraphRef> GraphRef for UndirectedAdaptor<G> {}
13
14impl<G> IntoNeighbors for UndirectedAdaptor<G>
15where
16 G: IntoNeighborsDirected,
17{
18 type Neighbors = std::iter::Chain<G::NeighborsDirected, G::NeighborsDirected>;
19 fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
20 self.0
21 .neighbors_directed(n, Direction::Incoming)
22 .chain(self.0.neighbors_directed(n, Direction::Outgoing))
23 }
24}
25
26impl<G> IntoEdges for UndirectedAdaptor<G>
27where
28 G: IntoEdgesDirected,
29{
30 type Edges = std::iter::Chain<G::EdgesDirected, G::EdgesDirected>;
31 fn edges(self, a: Self::NodeId) -> Self::Edges {
32 self.0
33 .edges_directed(a, Direction::Incoming)
34 .chain(self.0.edges_directed(a, Direction::Outgoing))
35 }
36}
37
38impl<G> GraphProp for UndirectedAdaptor<G>
39where
40 G: GraphBase,
41{
42 type EdgeType = crate::Undirected;
43
44 fn is_directed(&self) -> bool {
45 false
46 }
47}
48
49macro_rules! access0 {
50 ($e:expr) => {
51 $e.0
52 };
53}
54
55GraphBase! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
56Data! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
57IntoEdgeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
58Visitable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
59NodeIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
60NodeCompactIndexable! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
61IntoNodeIdentifiers! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
62IntoNodeReferences! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
63NodeCount! {delegate_impl [[G], G, UndirectedAdaptor<G>, access0]}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::graph::{DiGraph, Graph};
69 use crate::visit::Dfs;
70
71 static LINEAR_EDGES: [(u32, u32); 5] = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)];
72
73 #[test]
74 pub fn test_is_reachable() {
75 let graph = DiGraph::<(), ()>::from_edges(&LINEAR_EDGES);
79
80 let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
81 nodes.sort();
82
83 let graph = UndirectedAdaptor(&graph);
84
85 use crate::visit::Walker;
86 let mut visited_nodes: Vec<_> = Dfs::new(&graph, nodes[2]).iter(&graph).collect();
87 visited_nodes.sort();
88 assert_eq!(visited_nodes, nodes);
89 }
90
91 #[test]
92 pub fn test_neighbors_count() {
93 {
94 let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
95 let graph = UndirectedAdaptor(&graph);
96
97 let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
98 nodes.sort();
99 assert_eq!(graph.neighbors(nodes[1]).count(), 2);
100 }
101
102 {
103 let graph = Graph::<(), ()>::from_edges(&LINEAR_EDGES);
104 let graph = UndirectedAdaptor(&graph);
105
106 let mut nodes = graph.node_identifiers().collect::<Vec<_>>();
107 nodes.sort();
108 assert_eq!(graph.neighbors(nodes[1]).count(), 2);
109 }
110 }
111}