| //! A graph coupled with a mapping from arbitrary keys |
| //! into node indices. |
| |
| use std::hash::Hash; |
| use std::collections::HashMap; |
| use std::ops::{Index, IndexMut}; |
| use std::borrow::Borrow; |
| |
| use { |
| EdgeType, |
| }; |
| |
| use visit::{ |
| Graphlike, |
| }; |
| |
| use graph::{ |
| Graph, |
| IndexType, |
| NodeIndex, |
| EdgeIndex, |
| }; |
| |
| /// An input error in the builder |
| #[derive(Debug)] |
| pub struct BuilderError(()); |
| |
| /// `GraphBuilder` is a graph coupled with a mapping |
| /// from arbitrary keys into node indices. |
| /// |
| /// `GraphBuilder` can be used to quickly build a graph using hashable identifiers. |
| #[derive(Clone, Debug)] |
| pub struct GraphBuilder<Key, G> |
| where G: Graphlike, |
| Key: Hash + Eq, |
| { |
| graph: G, |
| node_map: HashMap<Key, G::NodeId> |
| } |
| |
| impl<Key, N, E, Ty, Ix> GraphBuilder<Key, Graph<N, E, Ty, Ix>> |
| where Ix: IndexType, |
| Ty: EdgeType, |
| Key: Eq + Hash, |
| { |
| pub fn from(graph: Graph<N, E, Ty, Ix>) -> Self { |
| let (node_cap, _) = graph.capacity(); |
| GraphBuilder { |
| node_map: HashMap::with_capacity(node_cap - graph.node_count()), |
| graph: graph, |
| } |
| } |
| |
| /// Add a node for `key` with `weight` if it does not exist. |
| pub fn ensure_node(&mut self, key: Key, weight: N) -> NodeIndex<Ix> { |
| let graph = &mut self.graph; |
| *self.node_map.entry(key).or_insert_with(|| { |
| graph.add_node(weight) |
| }) |
| } |
| |
| /// Add a node for `key` with weight taken from `f()` |
| /// if the node does not exist. |
| pub fn ensure_node_with<F>(&mut self, key: Key, f: F) -> NodeIndex<Ix> |
| where F: FnOnce() -> N, |
| { |
| let graph = &mut self.graph; |
| *self.node_map.entry(key).or_insert_with(|| { |
| graph.add_node(f()) |
| }) |
| } |
| |
| /// Add an edge from `a` to `b` (parallel edges allowed). |
| /// |
| /// **Panics** if either of the nodes don't exist. |
| pub fn add_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, |
| weight: E) -> EdgeIndex<Ix> |
| { |
| self.graph.add_edge(a, b, weight) |
| } |
| |
| /// Add or update an edge from `a` to `b`. |
| /// |
| /// **Panics** if either of the nodes don't exist. |
| pub fn update_edge(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>, |
| weight: E) -> EdgeIndex<Ix> |
| { |
| self.graph.update_edge(a, b, weight) |
| } |
| |
| /// Add or update an edge from `a` to `b`. |
| /// |
| /// Return an error if either of the nodes don't exist. |
| /// |
| /// **Panics** if the node map is inconsistent (key in map, but |
| /// corresponding node not in graph). |
| pub fn update_edge_by_key<Q>(&mut self, a: &Q, b: &Q, |
| weight: E) -> Result<EdgeIndex<Ix>, BuilderError> |
| where Key: Borrow<Q>, |
| Q: Eq + Hash, |
| { |
| if let (Some(&a), Some(&b)) = (self.node_map.get(a), self.node_map.get(b)) { |
| Ok(self.graph.update_edge(a, b, weight)) |
| } else { |
| Err(BuilderError(())) |
| } |
| } |
| } |
| |
| impl<Key, G> GraphBuilder<Key, G> |
| where G: Graphlike, |
| Key: Hash + Eq, |
| { |
| |
| /// Return a mutable reference to the graph |
| /// |
| /// **Note:** You should of course not do any operations that shift node |
| /// indices on the graph. |
| pub fn graph_mut(&mut self) -> &mut G { |
| &mut self.graph |
| } |
| |
| /// Return a mutable reference to the node map |
| /// |
| pub fn node_map_mut(&mut self) -> &mut HashMap<Key, G::NodeId> { |
| &mut self.node_map |
| } |
| |
| /// Split the builder into the node map and the graph |
| pub fn into_inner(self) -> (HashMap<Key, G::NodeId>, G) { |
| (self.node_map, self.graph) |
| } |
| |
| /// Split the builder into the graph |
| pub fn into_graph(self) -> G { |
| self.graph |
| } |
| } |
| |
| /// `GraphBuilder` can be indexed as if it were the underlying graph. |
| impl<Key, G, I> Index<I> for GraphBuilder<Key, G> |
| where G: Index<I> + Graphlike, |
| Key: Hash + Eq, |
| { |
| type Output = G::Output; |
| fn index(&self, index: I) -> &Self::Output { |
| &self.graph[index] |
| } |
| } |
| |
| /// `GraphBuilder` can be indexed as if it were the underlying graph. |
| impl<Key, G, I> IndexMut<I> for GraphBuilder<Key, G> |
| where G: IndexMut<I> + Graphlike, |
| Key: Hash + Eq, |
| { |
| fn index_mut(&mut self, index: I) -> &mut Self::Output { |
| &mut self.graph[index] |
| } |
| } |