visit: implement IntoEdges and IntoEdgesDirected for Reversed
Thanks to the previous change, this will work correctly on both directed and
undirected graphs.
Closes #292.
diff --git a/src/visit/reversed.rs b/src/visit/reversed.rs
index 29c6d48..ee5c772 100644
--- a/src/visit/reversed.rs
+++ b/src/visit/reversed.rs
@@ -7,6 +7,8 @@
use crate::visit::{
GraphBase,
GraphRef,
+ IntoEdges,
+ IntoEdgesDirected,
IntoNodeIdentifiers,
IntoNodeReferences,
IntoNeighbors,
@@ -57,6 +59,28 @@
}
}
+impl<G> IntoEdges for Reversed<G>
+ where G: IntoEdgesDirected
+{
+ type Edges = ReversedEdges<G::EdgesDirected>;
+ fn edges(self, a: Self::NodeId) -> Self::Edges {
+ ReversedEdges {
+ iter: self.0.edges_directed(a, Incoming),
+ }
+ }
+}
+
+impl<G> IntoEdgesDirected for Reversed<G>
+ where G: IntoEdgesDirected
+{
+ type EdgesDirected = ReversedEdges<G::EdgesDirected>;
+ fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::Edges {
+ ReversedEdges {
+ iter: self.0.edges_directed(a, dir.opposite()),
+ }
+ }
+}
+
impl<G: Visitable> Visitable for Reversed<G>
{
type Map = G::Map;
@@ -68,6 +92,19 @@
}
}
+/// A reversed edges iterator.
+pub struct ReversedEdges<I> {
+ iter: I,
+}
+
+impl<I> Iterator for ReversedEdges<I>
+ where I: Iterator, I::Item: EdgeRef
+{
+ type Item = ReversedEdgeReference<I::Item>;
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(ReversedEdgeReference)
+ }
+}
/// A reversed edge reference
#[derive(Copy, Clone, Debug)]
diff --git a/tests/graph.rs b/tests/graph.rs
index 6eaf804..8cfbb49 100644
--- a/tests/graph.rs
+++ b/tests/graph.rs
@@ -24,6 +24,8 @@
};
use petgraph::visit::{
+ IntoEdges,
+ IntoEdgesDirected,
IntoNodeIdentifiers,
NodeFiltered,
Reversed,
@@ -1141,9 +1143,18 @@
itertools::assert_equal(
gr.edges_directed(i, Outgoing),
gr.edges(i));
+
+ // Reversed reverses edges, so target and source need to be reversed once more.
+ itertools::assert_equal(
+ gr.edges_directed(i, Outgoing).map(|edge| (edge.source(), edge.target())),
+ Reversed(&gr).edges_directed(i, Incoming).map(|edge| (edge.target(), edge.source())));
+
for edge in gr.edges_directed(i, Outgoing) {
assert_eq!(edge.source(), i, "outgoing edges should have a fixed source");
}
+ for edge in Reversed(&gr).edges_directed(i, Incoming) {
+ assert_eq!(edge.target(), i, "reversed incoming edges should have a fixed target");
+ }
}
let mut reversed_gr = gr.clone();
@@ -1151,12 +1162,22 @@
println!("{:#?}", gr);
for i in gr.node_indices() {
+ // Compare against reversed graphs two different ways: using .reverse() and Reversed.
itertools::assert_equal(
gr.edges_directed(i, Incoming),
reversed_gr.edges(i));
+
+ // Reversed reverses edges, so target and source need to be reversed once more.
+ itertools::assert_equal(
+ gr.edges_directed(i, Incoming).map(|edge| (edge.source(), edge.target())),
+ Reversed(&gr).edges(i).map(|edge| (edge.target(), edge.source())));
+
for edge in gr.edges_directed(i, Incoming) {
assert_eq!(edge.target(), i, "incoming edges should have a fixed target");
}
+ for edge in Reversed(&gr).edges_directed(i, Outgoing) {
+ assert_eq!(edge.source(), i, "reversed outgoing edges should have a fixed source");
+ }
}
}
@@ -1168,17 +1189,36 @@
itertools::assert_equal(
gr.edges_directed(i, Outgoing),
gr.edges(i));
+
+ // Reversed reverses edges, so target and source need to be reversed once more.
+ itertools::assert_equal(
+ gr.edges_directed(i, Outgoing).map(|edge| (edge.source(), edge.target())),
+ Reversed(&gr).edges_directed(i, Incoming).map(|edge| (edge.target(), edge.source())));
+
for edge in gr.edges_directed(i, Outgoing) {
assert_eq!(edge.source(), i, "outgoing edges should have a fixed source");
}
+ for edge in Reversed(&gr).edges_directed(i, Incoming) {
+ assert_eq!(edge.target(), i, "reversed incoming edges should have a fixed target");
+ }
}
+
for i in gr.node_indices() {
itertools::assert_equal(
gr.edges_directed(i, Incoming),
gr.edges(i));
+
+ // Reversed reverses edges, so target and source need to be reversed once more.
+ itertools::assert_equal(
+ gr.edges_directed(i, Incoming).map(|edge| (edge.source(), edge.target())),
+ Reversed(&gr).edges(i).map(|edge| (edge.target(), edge.source())));
+
for edge in gr.edges_directed(i, Incoming) {
assert_eq!(edge.target(), i, "incoming edges should have a fixed target");
}
+ for edge in Reversed(&gr).edges_directed(i, Outgoing) {
+ assert_eq!(edge.source(), i, "reversed outgoing edges should have a fixed source");
+ }
}
}