use super::Graph;
pub trait GraphUpdate: Graph {
fn add_node(&mut self, node: Self::Node) -> Self::NodeIx;
fn add_edge(&mut self, edge: Self::Edge, from: Self::NodeIx, to: Self::NodeIx) -> Self::EdgeIx {
assert!(self.exists_node_index(from));
assert!(self.exists_node_index(to));
unsafe { self.add_edge_unchecked(edge, from, to) }
}
unsafe fn add_edge_unchecked(
&mut self,
edge: Self::Edge,
from: Self::NodeIx,
to: Self::NodeIx,
) -> Self::EdgeIx {
self.add_edge(edge, from, to)
}
fn append<G>(&mut self, mut other: G)
where
Self: Sized,
G: GraphUpdate<Node = Self::Node, Edge = Self::Edge>,
G: crate::graph::GraphRemove,
{
use std::collections::HashMap;
let edge_data: Vec<_> = other
.edge_indices()
.map(|edge_ix| {
let endpoints = unsafe { other.endpoints_unchecked(edge_ix) };
(edge_ix, endpoints)
})
.collect();
let node_indices: Vec<_> = other.node_indices().collect();
let (nodes, edges): (Vec<Self::Node>, Vec<Self::Edge>) = other.drain();
let mut node_mapping = HashMap::new();
for (old_node_ix, node) in node_indices.into_iter().zip(nodes) {
let new_node_ix = self.add_node(node);
node_mapping.insert(old_node_ix, new_node_ix);
}
for ((_, endpoints), edge) in edge_data.into_iter().zip(edges) {
let new_from = node_mapping[&endpoints[0]];
let new_to = node_mapping[&endpoints[1]];
unsafe { self.add_edge_unchecked(edge, new_from, new_to) };
}
}
}
impl<T: GraphUpdate> GraphUpdate for &mut T {
fn add_node(&mut self, node: Self::Node) -> Self::NodeIx {
(**self).add_node(node)
}
fn add_edge(&mut self, edge: Self::Edge, from: Self::NodeIx, to: Self::NodeIx) -> Self::EdgeIx {
(**self).add_edge(edge, from, to)
}
unsafe fn add_edge_unchecked(
&mut self,
edge: Self::Edge,
from: Self::NodeIx,
to: Self::NodeIx,
) -> Self::EdgeIx {
(**self).add_edge_unchecked(edge, from, to)
}
fn append<G>(&mut self, other: G)
where
Self: Sized,
G: GraphUpdate<Node = Self::Node, Edge = Self::Edge>,
G: crate::graph::GraphRemove,
{
(**self).append(other)
}
}