Skip to main content

rapier3d/data/
graph.rs

1// This is basically a stripped down version of petgraph's UnGraph.
2// - It is not generic with respect to the index type (we always use u32).
3// - It preserves associated edge iteration order after Serialization/Deserialization.
4// - It is always undirected.
5//! A stripped-down version of petgraph's UnGraph.
6use crate::alloc_prelude::*;
7
8use core::cmp::max;
9use core::ops::{Index, IndexMut};
10
11/// Node identifier.
12#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
13#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
14pub struct NodeIndex(u32);
15
16impl NodeIndex {
17    #[inline]
18    pub fn new(x: u32) -> Self {
19        NodeIndex(x)
20    }
21
22    #[inline]
23    pub fn index(self) -> usize {
24        self.0 as usize
25    }
26
27    #[inline]
28    pub fn end() -> Self {
29        NodeIndex(crate::INVALID_U32)
30    }
31
32    fn _into_edge(self) -> EdgeIndex {
33        EdgeIndex(self.0)
34    }
35}
36
37impl From<u32> for NodeIndex {
38    fn from(ix: u32) -> Self {
39        NodeIndex(ix)
40    }
41}
42
43/// Edge identifier.
44#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
45#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
46pub struct EdgeIndex(u32);
47
48impl EdgeIndex {
49    #[inline]
50    pub fn new(x: u32) -> Self {
51        EdgeIndex(x)
52    }
53
54    #[inline]
55    pub fn index(self) -> usize {
56        self.0 as usize
57    }
58
59    /// An invalid `EdgeIndex` used to denote absence of an edge, for example
60    /// to end an adjacency list.
61    #[inline]
62    pub fn end() -> Self {
63        EdgeIndex(crate::INVALID_U32)
64    }
65
66    fn _into_node(self) -> NodeIndex {
67        NodeIndex(self.0)
68    }
69}
70
71impl From<u32> for EdgeIndex {
72    fn from(ix: u32) -> Self {
73        EdgeIndex(ix)
74    }
75}
76
77#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
78#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
79pub enum Direction {
80    Outgoing = 0,
81    Incoming = 1,
82}
83
84impl Direction {
85    fn opposite(self) -> Direction {
86        match self {
87            Direction::Outgoing => Direction::Incoming,
88            Direction::Incoming => Direction::Outgoing,
89        }
90    }
91}
92
93const DIRECTIONS: [Direction; 2] = [Direction::Outgoing, Direction::Incoming];
94
95/// The graph's node type.
96#[derive(Debug, Copy, Clone)]
97#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
98pub struct Node<N> {
99    /// Associated node data.
100    pub weight: N,
101    /// Next edge in outgoing and incoming edge lists.
102    next: [EdgeIndex; 2],
103}
104
105/// The graph's edge type.
106#[derive(Debug, Copy, Clone)]
107#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
108pub struct Edge<E> {
109    /// Associated edge data.
110    pub weight: E,
111    /// Next edge in outgoing and incoming edge lists.
112    next: [EdgeIndex; 2],
113    /// Previous edge in outgoing and incoming edge lists (`EdgeIndex::end()`
114    /// when this edge is the list head stored on the node). Kept so unlinking
115    /// an edge — the broad-phase's bread and butter on churn-heavy scenes — is
116    /// O(1) instead of an O(degree) list walk per endpoint.
117    prev: [EdgeIndex; 2],
118    /// Start and End node index
119    node: [NodeIndex; 2],
120}
121
122impl<E> Edge<E> {
123    /// Return the source node index.
124    pub fn source(&self) -> NodeIndex {
125        self.node[0]
126    }
127
128    /// Return the target node index.
129    pub fn target(&self) -> NodeIndex {
130        self.node[1]
131    }
132}
133
134#[derive(Clone, Debug, Default)]
135#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
136pub struct Graph<N, E> {
137    pub(crate) nodes: Vec<Node<N>>,
138    pub(crate) edges: Vec<Edge<E>>,
139}
140
141enum Pair<T> {
142    Both(T, T),
143    One(T),
144    None,
145}
146
147/// Get mutable references at index `a` and `b`.
148fn index_twice<T>(arr: &mut [T], a: usize, b: usize) -> Pair<&mut T> {
149    if max(a, b) >= arr.len() {
150        Pair::None
151    } else if a == b {
152        Pair::One(&mut arr[max(a, b)])
153    } else {
154        // Never fails: a, b are in bounds and distinct.
155        let [ar, br] = arr
156            .get_disjoint_mut([a, b])
157            .expect("indices are in bounds and distinct");
158        Pair::Both(ar, br)
159    }
160}
161
162impl<N, E> Graph<N, E> {
163    /// Create a new `Graph` with estimated capacity.
164    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
165        Graph {
166            nodes: Vec::with_capacity(nodes),
167            edges: Vec::with_capacity(edges),
168        }
169    }
170
171    /// Add a node (also called vertex) with associated data `weight` to the graph.
172    ///
173    /// Computes in **O(1)** time.
174    ///
175    /// Return the index of the new node.
176    ///
177    /// **Panics** if the Graph is at the maximum number of nodes for its index
178    /// type (N/A if usize).
179    pub fn add_node(&mut self, weight: N) -> NodeIndex {
180        let node = Node {
181            weight,
182            next: [EdgeIndex::end(), EdgeIndex::end()],
183        };
184        assert!(self.nodes.len() != crate::INVALID_USIZE);
185        let node_idx = NodeIndex::new(self.nodes.len() as u32);
186        self.nodes.push(node);
187        node_idx
188    }
189
190    /// Access the weight for node `a`.
191    ///
192    /// Also available with indexing syntax: `&graph[a]`.
193    pub fn node_weight(&self, a: NodeIndex) -> Option<&N> {
194        self.nodes.get(a.index()).map(|n| &n.weight)
195    }
196
197    /// Access the weight for edge `a`.
198    ///
199    /// Also available with indexing syntax: `&graph[a]`.
200    pub fn edge_weight(&self, a: EdgeIndex) -> Option<&E> {
201        self.edges.get(a.index()).map(|e| &e.weight)
202    }
203
204    /// Access the weight for edge `a` mutably.
205    ///
206    /// Also available with indexing syntax: `&mut graph[a]`.
207    pub fn edge_weight_mut(&mut self, a: EdgeIndex) -> Option<&mut E> {
208        self.edges.get_mut(a.index()).map(|e| &mut e.weight)
209    }
210
211    /// Add an edge from `a` to `b` to the graph, with its associated
212    /// data `weight`.
213    ///
214    /// Return the index of the new edge.
215    ///
216    /// Computes in **O(1)** time.
217    ///
218    /// **Panics** if any of the nodes don't exist.<br>
219    /// **Panics** if the Graph is at the maximum number of edges for its index
220    /// type (N/A if usize).
221    ///
222    /// **Note:** `Graph` allows adding parallel (“duplicate”) edges. If you want
223    /// to avoid this, use [`.update_edge(a, b, weight)`](#method.update_edge) instead.
224    pub fn add_edge(&mut self, a: NodeIndex, b: NodeIndex, weight: E) -> EdgeIndex {
225        assert!(self.edges.len() != crate::INVALID_USIZE);
226        let edge_idx = EdgeIndex::new(self.edges.len() as u32);
227        let mut edge = Edge {
228            weight,
229            node: [a, b],
230            next: [EdgeIndex::end(); 2],
231            prev: [EdgeIndex::end(); 2],
232        };
233        match index_twice(&mut self.nodes, a.index(), b.index()) {
234            Pair::None => panic!("Graph::add_edge: node indices out of bounds"),
235            Pair::One(an) => {
236                edge.next = an.next;
237                an.next[0] = edge_idx;
238                an.next[1] = edge_idx;
239            }
240            Pair::Both(an, bn) => {
241                // a and b are different indices
242                edge.next = [an.next[0], bn.next[1]];
243                an.next[0] = edge_idx;
244                bn.next[1] = edge_idx;
245            }
246        }
247        // Back-links of the displaced list heads (doubly-linked adjacency).
248        for k in 0..2 {
249            let nxt = edge.next[k];
250            if nxt != EdgeIndex::end() {
251                self.edges[nxt.index()].prev[k] = edge_idx;
252            }
253        }
254        self.edges.push(edge);
255        edge_idx
256    }
257
258    /// Access the source and target nodes for `e`.
259    pub fn edge_endpoints(&self, e: EdgeIndex) -> Option<(NodeIndex, NodeIndex)> {
260        self.edges
261            .get(e.index())
262            .map(|ed| (ed.source(), ed.target()))
263    }
264
265    /// Remove `a` from the graph if it exists, and return its weight.
266    /// If it doesn't exist in the graph, return `None`.
267    ///
268    /// Apart from `a`, this invalidates the last node index in the graph
269    /// (that node will adopt the removed node index). Edge indices are
270    /// invalidated as they would be following the removal of each edge
271    /// with an endpoint in `a`.
272    ///
273    /// Computes in **O(e')** time, where **e'** is the number of affected
274    /// edges, including *n* calls to `.remove_edge()` where *n* is the number
275    /// of edges with an endpoint in `a`, and including the edges with an
276    /// endpoint in the displaced node.
277    pub fn remove_node(&mut self, a: NodeIndex) -> Option<N> {
278        self.remove_node_with(a, &mut |_| {})
279    }
280
281    /// Same as [`Self::remove_node`], invoking `on_remove` with each removed edge
282    /// index right before its removal is applied, so side arrays indexed like
283    /// `self.edges` can mirror the `swap_remove`s.
284    pub fn remove_node_with(
285        &mut self,
286        a: NodeIndex,
287        on_remove: &mut dyn FnMut(EdgeIndex),
288    ) -> Option<N> {
289        self.nodes.get(a.index())?;
290        for d in &DIRECTIONS {
291            let k = *d as usize;
292
293            // Remove all edges from and to this node.
294            loop {
295                let next = self.nodes[a.index()].next[k];
296                if next == EdgeIndex::end() {
297                    break;
298                }
299                let ret = self.remove_edge_with(next, on_remove);
300                debug_assert!(ret.is_some());
301                let _ = ret;
302            }
303        }
304
305        // Use swap_remove -- only the swapped-in node is going to change
306        // NodeIndex, so we only have to walk its edges and update them.
307
308        let node = self.nodes.swap_remove(a.index());
309
310        // Find the edge lists of the node that had to relocate.
311        // It may be that no node had to relocate, then we are done already.
312        let swap_edges = match self.nodes.get(a.index()) {
313            None => return Some(node.weight),
314            Some(ed) => ed.next,
315        };
316
317        // The swapped element's old index
318        let old_index = NodeIndex::new(self.nodes.len() as u32);
319        let new_index = a;
320
321        // Adjust the starts of the out edges, and ends of the in edges.
322        for &d in &DIRECTIONS {
323            let k = d as usize;
324            let mut edges = edges_walker_mut(&mut self.edges, swap_edges[k], d);
325            while let Some(curedge) = edges.next_edge() {
326                debug_assert!(curedge.node[k] == old_index);
327                curedge.node[k] = new_index;
328            }
329        }
330        Some(node.weight)
331    }
332
333    /// Unlinks edge `e` from the adjacency lists of both its endpoints, in O(1)
334    /// through the doubly-linked `prev`/`next` edge links. `e`'s own links are
335    /// left untouched (it is about to be removed or rewritten by the caller).
336    fn unlink_edge(&mut self, e: EdgeIndex) {
337        let (edge_node, edge_next, edge_prev) = {
338            let ed = &self.edges[e.index()];
339            (ed.node, ed.next, ed.prev)
340        };
341        for &d in &DIRECTIONS {
342            let k = d as usize;
343            let prev = edge_prev[k];
344            let next = edge_next[k];
345            if prev == EdgeIndex::end() {
346                // `e` is the list head stored on the node.
347                if let Some(node) = self.nodes.get_mut(edge_node[k].index()) {
348                    debug_assert!(node.next[k] == e);
349                    node.next[k] = next;
350                } else {
351                    debug_assert!(
352                        false,
353                        "Edge's endpoint dir={:?} index={:?} not found",
354                        d, edge_node[k]
355                    );
356                }
357            } else {
358                debug_assert!(self.edges[prev.index()].next[k] == e);
359                self.edges[prev.index()].next[k] = next;
360            }
361            if next != EdgeIndex::end() {
362                debug_assert!(self.edges[next.index()].prev[k] == e);
363                self.edges[next.index()].prev[k] = prev;
364            }
365        }
366    }
367
368    /// Rewrites the neighbors' (and head's) links pointing at edge `e` — whose
369    /// links are valid but whose index just changed — to `new_e`, in O(1)
370    /// through the doubly-linked edge links. The caller must already have moved
371    /// the edge's data to `new_e`'s slot.
372    fn relink_edge(&mut self, new_e: EdgeIndex) {
373        let (edge_node, edge_next, edge_prev) = {
374            let ed = &self.edges[new_e.index()];
375            (ed.node, ed.next, ed.prev)
376        };
377        for &d in &DIRECTIONS {
378            let k = d as usize;
379            let prev = edge_prev[k];
380            let next = edge_next[k];
381            if prev == EdgeIndex::end() {
382                if let Some(node) = self.nodes.get_mut(edge_node[k].index()) {
383                    node.next[k] = new_e;
384                }
385            } else {
386                self.edges[prev.index()].next[k] = new_e;
387            }
388            if next != EdgeIndex::end() {
389                self.edges[next.index()].prev[k] = new_e;
390            }
391        }
392    }
393
394    /// Remove an edge and return its edge weight, or `None` if it didn't exist.
395    ///
396    /// Apart from `e`, this invalidates the last edge index in the graph
397    /// (that edge will adopt the removed edge index).
398    ///
399    /// Computes in **O(e')** time, where **e'** is the size of four particular edge lists, for
400    /// the vertices of `e` and the vertices of another affected edge.
401    pub fn remove_edge(&mut self, e: EdgeIndex) -> Option<E> {
402        self.remove_edge_with(e, &mut |_| {})
403    }
404
405    /// Same as [`Self::remove_edge`], invoking `on_remove` with the edge index right
406    /// before the removal is applied, so side arrays indexed like `self.edges` can
407    /// mirror the `swap_remove`.
408    pub fn remove_edge_with(
409        &mut self,
410        e: EdgeIndex,
411        on_remove: &mut dyn FnMut(EdgeIndex),
412    ) -> Option<E> {
413        // every edge is part of two lists,
414        // outgoing and incoming edges.
415        // Remove it from both
416        self.edges.get(e.index())?;
417        self.unlink_edge(e);
418        on_remove(e);
419        self.remove_edge_adjust_indices(e)
420    }
421
422    fn remove_edge_adjust_indices(&mut self, e: EdgeIndex) -> Option<E> {
423        // swap_remove the edge -- only the removed edge
424        // and the edge swapped into place are affected and need updating
425        // indices.
426        let edge = self.edges.swap_remove(e.index());
427        if e.index() < self.edges.len() {
428            // An edge was swapped into the removed slot: rewrite the links
429            // pointing at its old index (the last slot) to `e`.
430            self.relink_edge(e);
431        }
432        Some(edge.weight)
433    }
434
435    /// Return an iterator of all edges of `a`.
436    ///
437    /// - `Directed`: Outgoing edges from `a`.
438    /// - `Undirected`: All edges connected to `a`.
439    ///
440    /// Produces an empty iterator if the node doesn't exist.<br>
441    /// Iterator element type is `EdgeReference<E, Ix>`.
442    pub fn edges(&self, a: NodeIndex) -> Edges<'_, E> {
443        self.edges_directed(a, Direction::Outgoing)
444    }
445
446    /// Return an iterator of all edges of `a`, in the specified direction.
447    ///
448    /// - `Directed`, `Outgoing`: All edges from `a`.
449    /// - `Directed`, `Incoming`: All edges to `a`.
450    /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each
451    ///   edge.
452    /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each
453    ///   edge.
454    ///
455    /// Produces an empty iterator if the node `a` doesn't exist.<br>
456    /// Iterator element type is `EdgeReference<E, Ix>`.
457    pub fn edges_directed(&self, a: NodeIndex, dir: Direction) -> Edges<'_, E> {
458        Edges {
459            skip_start: a,
460            edges: &self.edges,
461            direction: dir,
462            next: match self.nodes.get(a.index()) {
463                None => [EdgeIndex::end(), EdgeIndex::end()],
464                Some(n) => n.next,
465            },
466        }
467    }
468
469    /*
470    /// Return an iterator over all the edges connecting `a` and `b`.
471    ///
472    /// - `Directed`: Outgoing edges from `a`.
473    /// - `Undirected`: All edges connected to `a`.
474    ///
475    /// Iterator element type is `EdgeReference<E, Ix>`.
476    pub fn edges_connecting(&self, a: NodeIndex, b: NodeIndex) -> EdgesConnecting<E, Ty, Ix> {
477        EdgesConnecting {
478            target_node: b,
479            edges: self.edges_directed(a, Direction::Outgoing),
480            ty: PhantomData,
481        }
482    }
483    */
484
485    /// Lookup an edge from `a` to `b`.
486    ///
487    /// Computes in **O(e')** time, where **e'** is the number of edges
488    /// connected to `a` (and `b`, if the graph edges are undirected).
489    pub fn find_edge(&self, a: NodeIndex, b: NodeIndex) -> Option<EdgeIndex> {
490        self.find_edge_undirected(a, b).map(|(ix, _)| ix)
491    }
492
493    /// Return an iterator over all the edges connecting `a` and `b`, in either direction.
494    ///
495    /// Unlike [`Self::find_edge`], this yields every parallel edge between the two
496    /// nodes instead of only the first one found.
497    pub fn edges_between(
498        &self,
499        a: NodeIndex,
500        b: NodeIndex,
501    ) -> impl Iterator<Item = EdgeIndex> + '_ {
502        self.edges(a).filter_map(move |e| {
503            let node = self.edges[e.id().index()].node;
504            (node == [a, b] || node == [b, a]).then_some(e.id())
505        })
506    }
507
508    /// Lookup an edge between `a` and `b`, in either direction.
509    ///
510    /// If the graph is undirected, then this is equivalent to `.find_edge()`.
511    ///
512    /// Return the edge index and its directionality, with `Outgoing` meaning
513    /// from `a` to `b` and `Incoming` the reverse,
514    /// or `None` if the edge does not exist.
515    pub fn find_edge_undirected(
516        &self,
517        a: NodeIndex,
518        b: NodeIndex,
519    ) -> Option<(EdgeIndex, Direction)> {
520        match self.nodes.get(a.index()) {
521            None => None,
522            Some(node) => self.find_edge_undirected_from_node(node, b),
523        }
524    }
525
526    fn find_edge_undirected_from_node(
527        &self,
528        node: &Node<N>,
529        b: NodeIndex,
530    ) -> Option<(EdgeIndex, Direction)> {
531        for &d in &DIRECTIONS {
532            let k = d as usize;
533            let mut edix = node.next[k];
534            while let Some(edge) = self.edges.get(edix.index()) {
535                if edge.node[1 - k] == b {
536                    return Some((edix, d));
537                }
538                edix = edge.next[k];
539            }
540        }
541        None
542    }
543
544    /// Access the internal node array.
545    pub fn raw_nodes(&self) -> &[Node<N>] {
546        &self.nodes
547    }
548
549    /// Access the internal edge array.
550    pub fn raw_edges(&self) -> &[Edge<E>] {
551        &self.edges
552    }
553
554    /// Accessor for data structure internals: the first edge in the given direction.
555    pub fn first_edge(&self, a: NodeIndex, dir: Direction) -> Option<EdgeIndex> {
556        match self.nodes.get(a.index()) {
557            None => None,
558            Some(node) => {
559                let edix = node.next[dir as usize];
560                if edix == EdgeIndex::end() {
561                    None
562                } else {
563                    Some(edix)
564                }
565            }
566        }
567    }
568
569    /// Accessor for data structure internals: the next edge for the given direction.
570    pub fn next_edge(&self, e: EdgeIndex, dir: Direction) -> Option<EdgeIndex> {
571        match self.edges.get(e.index()) {
572            None => None,
573            Some(node) => {
574                let edix = node.next[dir as usize];
575                if edix == EdgeIndex::end() {
576                    None
577                } else {
578                    Some(edix)
579                }
580            }
581        }
582    }
583}
584
585struct EdgesWalkerMut<'a, E: 'a> {
586    edges: &'a mut [Edge<E>],
587    next: EdgeIndex,
588    dir: Direction,
589}
590
591fn edges_walker_mut<E>(
592    edges: &mut [Edge<E>],
593    next: EdgeIndex,
594    dir: Direction,
595) -> EdgesWalkerMut<'_, E> {
596    EdgesWalkerMut { edges, next, dir }
597}
598
599impl<E> EdgesWalkerMut<'_, E> {
600    fn next_edge(&mut self) -> Option<&mut Edge<E>> {
601        self.next().map(|t| t.1)
602    }
603
604    fn next(&mut self) -> Option<(EdgeIndex, &mut Edge<E>)> {
605        let this_index = self.next;
606        let k = self.dir as usize;
607        match self.edges.get_mut(self.next.index()) {
608            None => None,
609            Some(edge) => {
610                self.next = edge.next[k];
611                Some((this_index, edge))
612            }
613        }
614    }
615}
616
617/// Iterator over the edges of from or to a node
618pub struct Edges<'a, E: 'a> {
619    /// starting node to skip over
620    skip_start: NodeIndex,
621    edges: &'a [Edge<E>],
622
623    /// Next edge to visit.
624    next: [EdgeIndex; 2],
625
626    /// For directed graphs: the direction to iterate in
627    /// For undirected graphs: the direction of edges
628    direction: Direction,
629}
630
631impl<'a, E> Iterator for Edges<'a, E> {
632    type Item = EdgeReference<'a, E>;
633
634    fn next(&mut self) -> Option<Self::Item> {
635        //      type        direction    |    iterate over    reverse
636        //                               |
637        //    Directed      Outgoing     |      outgoing        no
638        //    Directed      Incoming     |      incoming        no
639        //   Undirected     Outgoing     |        both       incoming
640        //   Undirected     Incoming     |        both       outgoing
641
642        // For iterate_over, "both" is represented as None.
643        // For reverse, "no" is represented as None.
644        let (iterate_over, _reverse) = (None, Some(self.direction.opposite()));
645
646        if iterate_over.unwrap_or(Direction::Outgoing) == Direction::Outgoing {
647            let i = self.next[0].index();
648            if let Some(Edge {
649                node: _node,
650                weight,
651                next,
652                ..
653            }) = self.edges.get(i)
654            {
655                self.next[0] = next[0];
656                return Some(EdgeReference {
657                    index: EdgeIndex(i as u32),
658                    // node: if reverse == Some(Direction::Outgoing) {
659                    //     swap_pair(*node)
660                    // } else {
661                    //     *node
662                    // },
663                    weight,
664                });
665            }
666        }
667
668        if iterate_over.unwrap_or(Direction::Incoming) == Direction::Incoming {
669            while let Some(Edge {
670                node, weight, next, ..
671            }) = self.edges.get(self.next[1].index())
672            {
673                let edge_index = self.next[1];
674                self.next[1] = next[1];
675                // In any of the "both" situations, self-loops would be iterated over twice.
676                // Skip them here.
677                if iterate_over.is_none() && node[0] == self.skip_start {
678                    continue;
679                }
680
681                return Some(EdgeReference {
682                    index: edge_index,
683                    // node: if reverse == Some(Direction::Incoming) {
684                    //     swap_pair(*node)
685                    // } else {
686                    //     *node
687                    // },
688                    weight,
689                });
690            }
691        }
692
693        None
694    }
695}
696
697// fn swap_pair<T>(mut x: [T; 2]) -> [T; 2] {
698//     x.swap(0, 1);
699//     x
700// }
701
702impl<E> Clone for Edges<'_, E> {
703    fn clone(&self) -> Self {
704        Edges {
705            skip_start: self.skip_start,
706            edges: self.edges,
707            next: self.next,
708            direction: self.direction,
709        }
710    }
711}
712
713/// Index the `Graph` by `NodeIndex` to access node weights.
714///
715/// **Panics** if the node doesn't exist.
716impl<N, E> Index<NodeIndex> for Graph<N, E> {
717    type Output = N;
718    fn index(&self, index: NodeIndex) -> &N {
719        &self.nodes[index.index()].weight
720    }
721}
722
723/// Index the `Graph` by `NodeIndex` to access node weights.
724///
725/// **Panics** if the node doesn't exist.
726impl<N, E> IndexMut<NodeIndex> for Graph<N, E> {
727    fn index_mut(&mut self, index: NodeIndex) -> &mut N {
728        &mut self.nodes[index.index()].weight
729    }
730}
731
732/// Index the `Graph` by `EdgeIndex` to access edge weights.
733///
734/// **Panics** if the edge doesn't exist.
735impl<N, E> Index<EdgeIndex> for Graph<N, E> {
736    type Output = E;
737    fn index(&self, index: EdgeIndex) -> &E {
738        &self.edges[index.index()].weight
739    }
740}
741
742/// Index the `Graph` by `EdgeIndex` to access edge weights.
743///
744/// **Panics** if the edge doesn't exist.
745impl<N, E> IndexMut<EdgeIndex> for Graph<N, E> {
746    fn index_mut(&mut self, index: EdgeIndex) -> &mut E {
747        &mut self.edges[index.index()].weight
748    }
749}
750
751/// Reference to a `Graph` edge.
752#[derive(Debug)]
753pub struct EdgeReference<'a, E: 'a> {
754    index: EdgeIndex,
755    // node: [NodeIndex; 2],
756    weight: &'a E,
757}
758
759impl<'a, E: 'a> EdgeReference<'a, E> {
760    #[inline]
761    pub fn id(&self) -> EdgeIndex {
762        self.index
763    }
764
765    #[inline]
766    pub fn weight(&self) -> &'a E {
767        self.weight
768    }
769}
770
771impl<E> Clone for EdgeReference<'_, E> {
772    fn clone(&self) -> Self {
773        *self
774    }
775}
776
777impl<E> Copy for EdgeReference<'_, E> {}
778
779impl<E> PartialEq for EdgeReference<'_, E>
780where
781    E: PartialEq,
782{
783    fn eq(&self, rhs: &Self) -> bool {
784        self.index == rhs.index && self.weight == rhs.weight
785    }
786}