aboutsummaryrefslogtreecommitdiff
path: root/src/data/graph.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-08-25 22:10:25 +0200
committerSébastien Crozet <developer@crozet.re>2020-08-25 22:10:25 +0200
commit754a48b7ff6d8c58b1ee08651e60112900b60455 (patch)
tree7d777a6c003f1f5d8f8d24f533f35a95a88957fe /src/data/graph.rs
downloadrapier-754a48b7ff6d8c58b1ee08651e60112900b60455.tar.gz
rapier-754a48b7ff6d8c58b1ee08651e60112900b60455.tar.bz2
rapier-754a48b7ff6d8c58b1ee08651e60112900b60455.zip
First public release of Rapier.v0.1.0
Diffstat (limited to 'src/data/graph.rs')
-rw-r--r--src/data/graph.rs830
1 files changed, 830 insertions, 0 deletions
diff --git a/src/data/graph.rs b/src/data/graph.rs
new file mode 100644
index 0000000..ea27e03
--- /dev/null
+++ b/src/data/graph.rs
@@ -0,0 +1,830 @@
+// This is basically a stripped down version of petgraph's UnGraph.
+// - It is not generic wrt. the index type (we always use u32).
+// - It preserves associated edge iteration order after Serialization/Deserialization.
+// - It is always undirected.
+//! A stripped-down version of petgraph's UnGraph.
+
+use std::cmp::max;
+use std::ops::{Index, IndexMut};
+
+/// Node identifier.
+#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub struct NodeIndex(u32);
+
+impl NodeIndex {
+ #[inline]
+ pub fn new(x: u32) -> Self {
+ NodeIndex(x)
+ }
+
+ #[inline]
+ pub fn index(self) -> usize {
+ self.0 as usize
+ }
+
+ #[inline]
+ pub fn end() -> Self {
+ NodeIndex(crate::INVALID_U32)
+ }
+
+ fn _into_edge(self) -> EdgeIndex {
+ EdgeIndex(self.0)
+ }
+}
+
+impl From<u32> for NodeIndex {
+ fn from(ix: u32) -> Self {
+ NodeIndex(ix)
+ }
+}
+
+/// Edge identifier.
+#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub struct EdgeIndex(u32);
+
+impl EdgeIndex {
+ #[inline]
+ pub fn new(x: u32) -> Self {
+ EdgeIndex(x)
+ }
+
+ #[inline]
+ pub fn index(self) -> usize {
+ self.0 as usize
+ }
+
+ /// An invalid `EdgeIndex` used to denote absence of an edge, for example
+ /// to end an adjacency list.
+ #[inline]
+ pub fn end() -> Self {
+ EdgeIndex(crate::INVALID_U32)
+ }
+
+ fn _into_node(self) -> NodeIndex {
+ NodeIndex(self.0)
+ }
+}
+
+impl From<u32> for EdgeIndex {
+ fn from(ix: u32) -> Self {
+ EdgeIndex(ix)
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub enum Direction {
+ Outgoing = 0,
+ Incoming = 1,
+}
+
+impl Direction {
+ fn opposite(self) -> Direction {
+ match self {
+ Direction::Outgoing => Direction::Incoming,
+ Direction::Incoming => Direction::Outgoing,
+ }
+ }
+}
+
+const DIRECTIONS: [Direction; 2] = [Direction::Outgoing, Direction::Incoming];
+
+/// The graph's node type.
+#[derive(Debug, Copy, Clone)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub struct Node<N> {
+ /// Associated node data.
+ pub weight: N,
+ /// Next edge in outgoing and incoming edge lists.
+ next: [EdgeIndex; 2],
+}
+
+/// The graph's edge type.
+#[derive(Debug, Copy, Clone)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub struct Edge<E> {
+ /// Associated edge data.
+ pub weight: E,
+ /// Next edge in outgoing and incoming edge lists.
+ next: [EdgeIndex; 2],
+ /// Start and End node index
+ node: [NodeIndex; 2],
+}
+
+impl<E> Edge<E> {
+ /// Return the source node index.
+ pub fn source(&self) -> NodeIndex {
+ self.node[0]
+ }
+
+ /// Return the target node index.
+ pub fn target(&self) -> NodeIndex {
+ self.node[1]
+ }
+}
+
+#[derive(Clone, Debug)]
+#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
+pub struct Graph<N, E> {
+ pub(crate) nodes: Vec<Node<N>>,
+ pub(crate) edges: Vec<Edge<E>>,
+}
+
+enum Pair<T> {
+ Both(T, T),
+ One(T),
+ None,
+}
+
+/// Get mutable references at index `a` and `b`.
+fn index_twice<T>(arr: &mut [T], a: usize, b: usize) -> Pair<&mut T> {
+ if max(a, b) >= arr.len() {
+ Pair::None
+ } else if a == b {
+ Pair::One(&mut arr[max(a, b)])
+ } else {
+ // safe because a, b are in bounds and distinct
+ unsafe {
+ let ar = &mut *(arr.get_unchecked_mut(a) as *mut _);
+ let br = &mut *(arr.get_unchecked_mut(b) as *mut _);
+ Pair::Both(ar, br)
+ }
+ }
+}
+
+impl<N, E> Graph<N, E> {
+ /// Create a new `Graph` with estimated capacity.
+ pub fn with_capacity(nodes: usize, edges: usize) -> Self {
+ Graph {
+ nodes: Vec::with_capacity(nodes),
+ edges: Vec::with_capacity(edges),
+ }
+ }
+
+ /// Add a node (also called vertex) with associated data `weight` to the graph.
+ ///
+ /// Computes in **O(1)** time.
+ ///
+ /// Return the index of the new node.
+ ///
+ /// **Panics** if the Graph is at the maximum number of nodes for its index
+ /// type (N/A if usize).
+ pub fn add_node(&mut self, weight: N) -> NodeIndex {
+ let node = Node {
+ weight,
+ next: [EdgeIndex::end(), EdgeIndex::end()],
+ };
+ assert!(self.nodes.len() != crate::INVALID_USIZE);
+ let node_idx = NodeIndex::new(self.nodes.len() as u32);
+ self.nodes.push(node);
+ node_idx
+ }
+
+ /// Access the weight for node `a`.
+ ///
+ /// Also available with indexing syntax: `&graph[a]`.
+ pub fn node_weight(&self, a: NodeIndex) -> Option<&N> {
+ self.nodes.get(a.index()).map(|n| &n.weight)
+ }
+
+ /// Access the weight for edge `a`.
+ ///
+ /// Also available with indexing syntax: `&graph[a]`.
+ pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> {
+ self.edges.get(a.index()).map(|e| &e.weight)
+ }
+
+ /// Access the weight for edge `a` mutably.
+ ///
+ /// Also available with indexing syntax: `&mut graph[a]`.
+ pub fn edge_weight_mut(&mut self, a: EdgeIndex) -> Option<&mut E> {
+ self.edges.get_mut(a.index()).map(|e| &mut e.weight)
+ }
+
+ /// Add an edge from `a` to `b` to the graph, with its associated
+ /// data `weight`.
+ ///
+ /// Return the index of the new edge.
+ ///
+ /// Computes in **O(1)** time.
+ ///
+ /// **Panics** if any of the nodes don't exist.<br>
+ /// **Panics** if the Graph is at the maximum number of edges for its index
+ /// type (N/A if usize).
+ ///
+ /// **Note:** `Graph` allows adding parallel (“duplicate”) edges. If you want
+ /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead.
+ pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex {
+ assert!(self.edges.len() != crate::INVALID_USIZE);
+ let edge_idx = EdgeIndex::new(self.edges.len() as u32);
+ let mut edge = Edge {
+ weight,
+ node: [a, b],
+ next: [EdgeIndex::end(); 2],
+ };
+ match index_twice(&mut self.nodes, a.index(), b.index()) {
+ Pair::None => panic!("Graph::add_edge: node indices out of bounds"),
+ Pair::One(an) => {
+ edge.next = an.next;
+ an.next[0] = edge_idx;
+ an.next[1] = edge_idx;
+ }
+ Pair::Both(an, bn) => {
+ // a and b are different indices
+ edge.next = [an.next[0], bn.next[1]];
+ an.next[0] = edge_idx;
+ bn.next[1] = edge_idx;
+ }
+ }
+ self.edges.push(edge);
+ edge_idx
+ }
+
+ /// Access the source and target nodes for `e`.
+ pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> {
+ self.edges
+ .get(e.index())
+ .map(|ed| (ed.source(), ed.target()))
+ }
+
+ /// Remove `a` from the graph if it exists, and return its weight.
+ /// If it doesn't exist in the graph, return `None`.
+ ///
+ /// Apart from `a`, this invalidates the last node index in the graph
+ /// (that node will adopt the removed node index). Edge indices are
+ /// invalidated as they would be following the removal of each edge
+ /// with an endpoint in `a`.
+ ///
+ /// Computes in **O(e')** time, where **e'** is the number of affected
+ /// edges, including *n* calls to `.remove_edge()` where *n* is the number
+ /// of edges with an endpoint in `a`, and including the edges with an
+ /// endpoint in the displaced node.
+ pub fn remove_node(&mut self, a: NodeIndex) -> Option<N> {
+ self.nodes.get(a.index())?;
+ for d in &DIRECTIONS {
+ let k = *d as usize;
+
+ // Remove all edges from and to this node.
+ loop {
+ let next = self.nodes[a.index()].next[k];
+ if next == EdgeIndex::end() {
+ break;
+ }
+ let ret = self.remove_edge(next);
+ debug_assert!(ret.is_some());
+ let _ = ret;
+ }
+ }
+
+ // Use swap_remove -- only the swapped-in node is going to change
+ // NodeIndex, so we only have to walk its edges and update them.
+
+ let node = self.nodes.swap_remove(a.index());
+
+ // Find the edge lists of the node that had to relocate.
+ // It may be that no node had to relocate, then we are done already.
+ let swap_edges = match self.nodes.get(a.index()) {
+ None => return Some(node.weight),
+ Some(ed) => ed.next,
+ };
+
+ // The swapped element's old index
+ let old_index = NodeIndex::new(self.nodes.len() as u32);
+ let new_index = a;
+
+ // Adjust the starts of the out edges, and ends of the in edges.
+ for &d in &DIRECTIONS {
+ let k = d as usize;
+ let mut edges = edges_walker_mut(&mut self.edges, swap_edges[k], d);
+ while let Some(curedge) = edges.next_edge() {
+ debug_assert!(curedge.node[k] == old_index);
+ curedge.node[k] = new_index;
+ }
+ }
+ Some(node.weight)
+ }
+
+ /// For edge `e` with endpoints `edge_node`, replace links to it,
+ /// with links to `edge_next`.
+ fn change_edge_links(
+ &mut self,
+ edge_node: [NodeIndex; 2],
+ e: EdgeIndex,
+ edge_next: [EdgeIndex; 2],
+ ) {
+ for &d in &DIRECTIONS {
+ let k = d as usize;
+ let node = match self.nodes.get_mut(edge_node[k].index()) {
+ Some(r) => r,
+ None => {
+ debug_assert!(
+ false,
+ "Edge's endpoint dir={:?} index={:?} not found",
+ d, edge_node[k]
+ );
+ return;
+ }
+ };
+ let fst = node.next[k];
+ if fst == e {
+ //println!("Updating first edge 0 for node {}, set to {}", edge_node[0], edge_next[0]);
+ node.next[k] = edge_next[k];
+ } else {
+ let mut edges = edges_walker_mut(&mut self.edges, fst, d);
+ while let Some(curedge) = edges.next_edge() {
+ if curedge.next[k] == e {
+ curedge.next[k] = edge_next[k];
+ break; // the edge can only be present once in the list.
+ }
+ }
+ }
+ }
+ }
+
+ /// Remove an edge and return its edge weight, or `None` if it didn't exist.
+ ///
+ /// Apart from `e`, this invalidates the last edge index in the graph
+ /// (that edge will adopt the removed edge index).
+ ///
+ /// Computes in **O(e')** time, where **e'** is the size of four particular edge lists, for
+ /// the vertices of `e` and the vertices of another affected edge.
+ pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E> {
+ // every edge is part of two lists,
+ // outgoing and incoming edges.
+ // Remove it from both
+ let (edge_node, edge_next) = match self.edges.get(e.index()) {
+ None => return None,
+ Some(x) => (x.node, x.next),
+ };
+ // Remove the edge from its in and out lists by replacing it with
+ // a link to the next in the list.
+ self.change_edge_links(edge_node, e, edge_next);
+ self.remove_edge_adjust_indices(e)
+ }
+
+ fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option<E> {
+ // swap_remove the edge -- only the removed edge
+ // and the edge swapped into place are affected and need updating
+ // indices.
+ let edge = self.edges.swap_remove(e.index());
+ let swap = match self.edges.get(e.index()) {
+ // no elment needed to be swapped.
+ None => return Some(edge.weight),
+ Some(ed) => ed.node,
+ };
+ let swapped_e = EdgeIndex::new(self.edges.len() as u32);
+
+ // Update the edge lists by replacing links to the old index by references to the new
+ // edge index.
+ self.change_edge_links(swap, swapped_e, [e, e]);
+ Some(edge.weight)
+ }
+
+ /// Return an iterator of all edges of `a`.
+ ///
+ /// - `Directed`: Outgoing edges from `a`.
+ /// - `Undirected`: All edges connected to `a`.
+ ///
+ /// Produces an empty iterator if the node doesn't exist.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges(&self, a: NodeIndex) -> Edges<E> {
+ self.edges_directed(a, Direction::Outgoing)
+ }
+
+ /// Return an iterator of all edges of `a`, in the specified direction.
+ ///
+ /// - `Directed`, `Outgoing`: All edges from `a`.
+ /// - `Directed`, `Incoming`: All edges to `a`.
+ /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each
+ /// edge.
+ /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each
+ /// edge.
+ ///
+ /// Produces an empty iterator if the node `a` doesn't exist.<br>
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges_directed(&self, a: NodeIndex, dir: Direction) -> Edges<E> {
+ Edges {
+ skip_start: a,
+ edges: &self.edges,
+ direction: dir,
+ next: match self.nodes.get(a.index()) {
+ None => [EdgeIndex::end(), EdgeIndex::end()],
+ Some(n) => n.next,
+ },
+ }
+ }
+
+ /*
+ /// Return an iterator over all the edges connecting `a` and `b`.
+ ///
+ /// - `Directed`: Outgoing edges from `a`.
+ /// - `Undirected`: All edges connected to `a`.
+ ///
+ /// Iterator element type is `EdgeReference<E, Ix>`.
+ pub fn edges_connecting(&self, a: NodeIndex, b: NodeIndex) -> EdgesConnecting<E, Ty, Ix> {
+ EdgesConnecting {
+ target_node: b,
+ edges: self.edges_directed(a, Direction::Outgoing),
+ ty: PhantomData,
+ }
+ }
+ */
+
+ /// Lookup an edge from `a` to `b`.
+ ///
+ /// Computes in **O(e')** time, where **e'** is the number of edges
+ /// connected to `a` (and `b`, if the graph edges are undirected).
+ pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option<EdgeIndex> {
+ self.find_edge_undirected(a, b).map(|(ix, _)| ix)
+ }
+
+ /// Lookup an edge between `a` and `b`, in either direction.
+ ///
+ /// If the graph is undirected, then this is equivalent to `.find_edge()`.
+ ///
+ /// Return the edge index and its directionality, with `Outgoing` meaning
+ /// from `a` to `b` and `Incoming` the reverse,
+ /// or `None` if the edge does not exist.
+ pub fn find_edge_undirected(
+ &self,
+ a: NodeIndex,
+ b: NodeIndex,
+ ) -> Option<(EdgeIndex, Direction)> {
+ match self.nodes.get(a.index()) {
+ None => None,
+ Some(node) => self.find_edge_undirected_from_node(node, b),
+ }
+ }
+
+ fn find_edge_undirected_from_node(
+ &self,
+ node: &Node<N>,
+ b: NodeIndex,
+ ) -> Option<(EdgeIndex, Direction)> {
+ for &d in &DIRECTIONS {
+ let k = d as usize;
+ let mut edix = node.next[k];
+ while let Some(edge) = self.edges.get(edix.index()) {
+ if edge.node[1 - k] == b {
+ return Some((edix, d));
+ }
+ edix = edge.next[k];
+ }
+ }
+ None
+ }
+
+ /// Access the internal node array.
+ pub fn raw_nodes(&self) -> &[Node<N>] {
+ &self.nodes
+ }
+
+ /// Access the internal edge array.
+ pub fn raw_edges(&self) -> &[Edge<E>] {
+ &self.edges
+ }
+
+ /// Accessor for data structure internals: the first edge in the given direction.
+ pub fn first_edge(&self, a: NodeIndex, dir: Direction) -> Option<EdgeIndex> {
+ match self.nodes.get(a.index()) {
+ None => None,
+ Some(node) => {
+ let edix = node.next[dir as usize];
+ if edix == EdgeIndex::end() {
+ None
+ } else {
+ Some(edix)
+ }
+ }
+ }
+ }
+
+ /// Accessor for data structure internals: the next edge for the given direction.
+ pub fn next_edge(&self, e: EdgeIndex, dir: Direction) -> Option<EdgeIndex> {
+ match self.edges.get(e.index()) {
+ None => None,
+ Some(node) => {
+ let edix = node.next[dir as usize];
+ if edix == EdgeIndex::end() {
+ None
+ } else {
+ Some(edix)
+ }
+ }
+ }
+ }
+}
+
+/// An iterator over either the nodes without edges to them or from them.
+pub struct Externals<'a, N: 'a> {
+ iter: std::iter::Enumerate<std::slice::Iter<'a, Node<N>>>,
+ dir: Direction,
+}
+
+impl<'a, N: 'a> Iterator for Externals<'a, N> {
+ type Item = NodeIndex;
+ fn next(&mut self) -> Option<NodeIndex> {
+ let k = self.dir as usize;
+ loop {
+ match self.iter.next() {
+ None => return None,
+ Some((index, node)) => {
+ if node.next[k] == EdgeIndex::end() && node.next[1 - k] == EdgeIndex::end() {
+ return Some(NodeIndex::new(index as u32));
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Iterator over the neighbors of a node.
+///
+/// Iterator element type is `NodeIndex`.
+///
+/// Created with [`.neighbors()`][1], [`.neighbors_directed()`][2] or
+/// [`.neighbors_undirected()`][3].
+///
+/// [1]: struct.Graph.html#method.neighbors
+/// [2]: struct.Graph.html#method.neighbors_directed
+/// [3]: struct.Graph.html#method.neighbors_undirected
+pub struct Neighbors<'a, E: 'a> {
+ /// starting node to skip over
+ skip_start: NodeIndex,
+ edges: &'a [Edge<E>],
+ next: [EdgeIndex; 2],
+}
+
+impl<'a, E> Iterator for Neighbors<'a, E> {
+ type Item = NodeIndex;
+
+ fn next(&mut self) -> Option<NodeIndex> {
+ // First any outgoing edges
+ match self.edges.get(self.next[0].index()) {
+ None => {}
+ Some(edge) => {
+ self.next[0] = edge.next[0];
+ return Some(edge.node[1]);
+ }
+ }
+ // Then incoming edges
+ // For an "undirected" iterator (traverse both incoming
+ // and outgoing edge lists), make sure we don't double
+ // count selfloops by skipping them in the incoming list.
+ while let Some(edge) = self.edges.get(self.next[1].index()) {
+ self.next[1] = edge.next[1];
+ if edge.node[0] != self.skip_start {
+ return Some(edge.node[0]);
+ }
+ }
+ None
+ }
+}
+
+struct EdgesWalkerMut<'a, E: 'a> {
+ edges: &'a mut [Edge<E>],
+ next: EdgeIndex,
+ dir: Direction,
+}
+
+fn edges_walker_mut<E>(
+ edges: &mut [Edge<E>],
+ next: EdgeIndex,
+ dir: Direction,
+) -> EdgesWalkerMut<E> {
+ EdgesWalkerMut { edges, next, dir }
+}
+
+impl<'a, E> EdgesWalkerMut<'a, E> {
+ fn next_edge(&mut self) -> Option<&mut Edge<E>> {
+ self.next().map(|t| t.1)
+ }
+
+ fn next(&mut self) -> Option<(EdgeIndex, &mut Edge<E>)> {
+ let this_index = self.next;
+ let k = self.dir as usize;
+ match self.edges.get_mut(self.next.index()) {
+ None => None,
+ Some(edge) => {
+ self.next = edge.next[k];
+ Some((this_index, edge))
+ }
+ }
+ }
+}
+
+/// Iterator over the edges of from or to a node
+pub struct Edges<'a, E: 'a> {
+ /// starting node to skip over
+ skip_start: NodeIndex,
+ edges: &'a [Edge<E>],
+
+ /// Next edge to visit.
+ next: [EdgeIndex; 2],
+
+ /// For directed graphs: the direction to iterate in
+ /// For undirected graphs: the direction of edges
+ direction: Direction,
+}
+
+impl<'a, E> Iterator for Edges<'a, E> {
+ type Item = EdgeReference<'a, E>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ // type direction | iterate over reverse
+ // |
+ // Directed Outgoing | outgoing no
+ // Directed Incoming | incoming no
+ // Undirected Outgoing | both incoming
+ // Undirected Incoming | both outgoing
+
+ // For iterate_over, "both" is represented as None.
+ // For reverse, "no" is represented as None.
+ let (iterate_over, reverse) = (None, Some(self.direction.opposite()));
+
+ if iterate_over.unwrap_or(Direction::Outgoing) == Direction::Outgoing {
+ let i = self.next[0].index();
+ if let Some(Edge { node, weight, next }) = self.edges.get(i) {
+ self.next[0] = next[0];
+ return Some(EdgeReference {
+ index: EdgeIndex(i as u32),
+ node: if reverse == Some(Direction::Outgoing) {
+ swap_pair(*node)
+ } else {
+ *node
+ },
+ weight,
+ });
+ }
+ }
+
+ if iterate_over.unwrap_or(Direction::Incoming) == Direction::Incoming {
+ while let Some(Edge { node, weight, next }) = self.edges.get(self.next[1].index()) {
+ let edge_index = self.next[1];
+ self.next[1] = next[1];
+ // In any of the "both" situations, self-loops would be iterated over twice.
+ // Skip them here.
+ if iterate_over.is_none() && node[0] == self.skip_start {
+ continue;
+ }
+
+ return Some(EdgeReference {
+ index: edge_index,
+ node: if reverse == Some(Direction::Incoming) {
+ swap_pair(*node)
+ } else {
+ *node
+ },
+ weight,
+ });
+ }
+ }
+
+ None
+ }
+}
+
+fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
+ x.swap(0, 1);
+ x
+}
+
+impl<'a, E> Clone for Edges<'a, E> {
+ fn clone(&self) -> Self {
+ Edges {
+ skip_start: self.skip_start,
+ edges: self.edges,
+ next: self.next,
+ direction: self.direction,
+ }
+ }
+}
+
+/// Index the `Graph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E> Index<NodeIndex> for Graph<N, E> {
+ type Output = N;
+ fn index(&self, index: NodeIndex) -> &N {
+ &self.nodes[index.index()].weight
+ }
+}
+
+/// Index the `Graph` by `NodeIndex` to access node weights.
+///
+/// **Panics** if the node doesn't exist.
+impl<N, E> IndexMut<NodeIndex> for Graph<N, E> {
+ fn index_mut(&mut self, index: NodeIndex) -> &mut N {
+ &mut self.nodes[index.index()].weight
+ }
+}
+
+/// Index the `Graph` by `EdgeIndex` to access edge weights.
+///
+/// **Panics** if the edge doesn't exist.
+impl<N, E> Index<EdgeIndex> for Graph<N, E> {
+ type Output = E;
+ fn index(&self, index: EdgeIndex) -> &E {
+ &self.edges[index.index()].weight
+ }
+}
+
+/// Index the `Graph` by `EdgeIndex` to access edge weights.
+///
+/// **Panics** if the edge doesn't exist.
+impl<N, E> IndexMut<EdgeIndex> for Graph<N, E> {
+ fn index_mut(&mut self, index: EdgeIndex) -> &mut E {
+ &mut self.edges[index.index()].weight
+ }
+}
+
+/// A “walker” object that can be used to step through the edge list of a node.
+///
+/// Created with [`.detach()`](struct.Neighbors.html#method.detach).
+///
+/// The walker does not borrow from the graph, so it lets you step through
+/// neighbors or incident edges while also mutating graph weights, as
+/// in the following example:
+pub struct WalkNeighbors {
+ skip_start: NodeIndex,
+ next: [EdgeIndex; 2],
+}
+
+impl Clone for WalkNeighbors {
+ fn clone(&self) -> Self {
+ WalkNeighbors {
+ skip_start: self.skip_start,
+ next: self.next,
+ }
+ }
+}
+
+/// Reference to a `Graph` edge.
+#[derive(Debug)]
+pub struct EdgeReference<'a, E: 'a> {
+ index: EdgeIndex,
+ node: [NodeIndex; 2],
+ weight: &'a E,
+}
+
+impl<'a, E: 'a> EdgeReference<'a, E> {
+ #[inline]
+ pub fn id(&self) -> EdgeIndex {
+ self.index
+ }
+
+ #[inline]
+ pub fn weight(&self) -> &'a E {
+ self.weight
+ }
+}
+
+impl<'a, E> Clone for EdgeReference<'a, E> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<'a, E> Copy for EdgeReference<'a, E> {}
+
+impl<'a, E> PartialEq for EdgeReference<'a, E>
+where
+ E: PartialEq,
+{
+ fn eq(&self, rhs: &Self) -> bool {
+ self.index == rhs.index && self.weight == rhs.weight
+ }
+}
+
+/// Iterator over all nodes of a graph.
+pub struct NodeReferences<'a, N: 'a> {
+ iter: std::iter::Enumerate<std::slice::Iter<'a, Node<N>>>,
+}
+
+impl<'a, N> Iterator for NodeReferences<'a, N> {
+ type Item = (NodeIndex, &'a N);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next()
+ .map(|(i, node)| (NodeIndex::new(i as u32), &node.weight))
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.iter.size_hint()
+ }
+}
+
+impl<'a, N> DoubleEndedIterator for NodeReferences<'a, N> {
+ fn next_back(&mut self) -> Option<Self::Item> {
+ self.iter
+ .next_back()
+ .map(|(i, node)| (NodeIndex::new(i as u32), &node.weight))
+ }
+}
+
+impl<'a, N> ExactSizeIterator for NodeReferences<'a, N> {}