petgraph/
graphmap.rs

1//! `GraphMap<N, E, Ty>` is a graph datastructure where node values are mapping
2//! keys.
3
4use alloc::vec::Vec;
5use core::{
6    cmp::Ordering,
7    fmt,
8    hash::{self, BuildHasher, Hash},
9    iter::{Copied, FromIterator},
10    marker::PhantomData,
11    mem,
12    ops::{Deref, Index, IndexMut},
13    slice::Iter,
14};
15
16use hashbrown::HashSet;
17use indexmap::{
18    map::{Iter as IndexMapIter, IterMut as IndexMapIterMut, Keys},
19    IndexMap,
20};
21
22use crate::{
23    data,
24    graph::{node_index, Graph},
25    visit, Directed, Direction, EdgeType, Incoming, IntoWeightedEdge, Outgoing, Undirected,
26};
27
28#[cfg(feature = "std")]
29use std::collections::hash_map::RandomState;
30
31#[cfg(feature = "rayon")]
32use {
33    indexmap::map::rayon::{ParIter, ParIterMut, ParKeys},
34    rayon::prelude::*,
35};
36
37/// A `GraphMap` with undirected edges.
38///
39/// For example, an edge between *1* and *2* is equivalent to an edge between
40/// *2* and *1*.
41pub type UnGraphMap<N, E, #[cfg(not(feature = "std"))] S, #[cfg(feature = "std")] S = RandomState> =
42    GraphMap<N, E, Undirected, S>;
43/// A `GraphMap` with directed edges.
44///
45/// For example, an edge from *1* to *2* is distinct from an edge from *2* to
46/// *1*.
47pub type DiGraphMap<N, E, #[cfg(not(feature = "std"))] S, #[cfg(feature = "std")] S = RandomState> =
48    GraphMap<N, E, Directed, S>;
49
50/// `GraphMap<N, E, Ty>` is a graph datastructure using an associative array
51/// of its node weights `N`.
52///
53/// It uses an combined adjacency list and sparse adjacency matrix
54/// representation, using **O(|V| + |E|)** space where V is the set of nodes
55/// and E is the set of edges, and allows testing for edge
56/// existence in constant time.
57///
58/// `GraphMap` is parameterized over:
59///
60/// - Associated data `N` for nodes and `E` for edges, called *weights*.
61/// - The node weight `N` must implement `Copy` and will be used as node
62///   identifier, duplicated into several places in the data structure.
63///   It must be suitable as a hash table key (implementing `Eq + Hash`).
64///   The node type must also implement `Ord` so that the implementation can
65///   order the pair (`a`, `b`) for an edge connecting any two nodes `a` and `b`.
66/// - `E` can be of arbitrary type.
67/// - Edge type `Ty` that determines whether the graph edges are directed or
68///   undirected.
69///
70/// You can use the type aliases `UnGraphMap` and `DiGraphMap` for convenience.
71///
72/// `GraphMap` does not allow parallel edges, but self loops are allowed.
73///
74/// Depends on crate feature `graphmap` (default).
75#[derive(Clone)]
76pub struct GraphMap<
77    N,
78    E,
79    Ty,
80    #[cfg(not(feature = "std"))] S,
81    #[cfg(feature = "std")] S = RandomState,
82> where
83    S: BuildHasher,
84{
85    nodes: IndexMap<N, Vec<(N, CompactDirection)>, S>,
86    edges: IndexMap<(N, N), E, S>,
87    ty: PhantomData<Ty>,
88}
89
90impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug, Ty: EdgeType, S: BuildHasher> fmt::Debug
91    for GraphMap<N, E, Ty, S>
92{
93    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
94        self.nodes.fmt(f)
95    }
96}
97
98/// A trait group for `GraphMap`'s node identifier.
99pub trait NodeTrait: Copy + Ord + Hash {}
100impl<N> NodeTrait for N where N: Copy + Ord + Hash {}
101
102// non-repr(usize) version of Direction
103#[derive(Copy, Clone, Debug, PartialEq)]
104enum CompactDirection {
105    Outgoing,
106    Incoming,
107}
108
109impl CompactDirection {
110    /// Return the opposite `CompactDirection`.
111    #[inline]
112    pub fn opposite(self) -> CompactDirection {
113        match self {
114            CompactDirection::Outgoing => CompactDirection::Incoming,
115            CompactDirection::Incoming => CompactDirection::Outgoing,
116        }
117    }
118}
119
120impl From<Direction> for CompactDirection {
121    fn from(d: Direction) -> Self {
122        match d {
123            Outgoing => CompactDirection::Outgoing,
124            Incoming => CompactDirection::Incoming,
125        }
126    }
127}
128
129impl From<CompactDirection> for Direction {
130    fn from(d: CompactDirection) -> Self {
131        match d {
132            CompactDirection::Outgoing => Outgoing,
133            CompactDirection::Incoming => Incoming,
134        }
135    }
136}
137
138impl PartialEq<Direction> for CompactDirection {
139    fn eq(&self, rhs: &Direction) -> bool {
140        (*self as usize) == (*rhs as usize)
141    }
142}
143
144#[cfg(feature = "serde-1")]
145impl<N, E, Ty, S> serde::Serialize for GraphMap<N, E, Ty, S>
146where
147    Ty: EdgeType,
148    N: NodeTrait + serde::Serialize,
149    E: serde::Serialize,
150    S: BuildHasher,
151    Self: Clone,
152{
153    /// Serializes the given `GraphMap` into the same format as the standard
154    /// `Graph`. Needs feature `serde-1`.
155    ///
156    /// Note: the graph has to be `Clone` for this to work.
157    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
158    where
159        Ser: serde::Serializer,
160    {
161        let cloned_graph: GraphMap<N, E, Ty, S> = GraphMap::clone(self);
162        let equivalent_graph: Graph<N, E, Ty, u32> = cloned_graph.into_graph();
163        equivalent_graph.serialize(serializer)
164    }
165}
166
167#[cfg(feature = "serde-1")]
168impl<'de, N, E, Ty, S> serde::Deserialize<'de> for GraphMap<N, E, Ty, S>
169where
170    Ty: EdgeType,
171    N: NodeTrait + serde::Deserialize<'de>,
172    E: Clone + serde::Deserialize<'de>,
173    S: BuildHasher + Default,
174{
175    /// Deserializes into a new `GraphMap` from the same format as the standard
176    /// `Graph`. Needs feature `serde-1`.
177    ///
178    /// **Warning**: When deseralizing a graph that was not originally a `GraphMap`,
179    /// the restrictions from [`from_graph`](#method.from_graph) apply.
180    ///
181    /// Note: The edge weights have to be `Clone` for this to work.
182    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
183    where
184        D: serde::Deserializer<'de>,
185    {
186        let equivalent_graph: Graph<N, E, Ty, u32> = Graph::deserialize(deserializer)?;
187        Ok(GraphMap::from_graph(equivalent_graph))
188    }
189}
190
191impl<N, E, Ty, S> GraphMap<N, E, Ty, S>
192where
193    N: NodeTrait,
194    Ty: EdgeType,
195    S: BuildHasher,
196{
197    /// Create a new `GraphMap`
198    pub fn new() -> Self
199    where
200        S: Default,
201    {
202        Self::default()
203    }
204
205    /// Create a new `GraphMap` with estimated capacity.
206    pub fn with_capacity(nodes: usize, edges: usize) -> Self
207    where
208        S: Default,
209    {
210        Self {
211            nodes: IndexMap::with_capacity_and_hasher(nodes, S::default()),
212            edges: IndexMap::with_capacity_and_hasher(edges, S::default()),
213            ty: PhantomData,
214        }
215    }
216
217    /// Create a new `GraphMap` with estimated capacity, and specified hasher.
218    pub fn with_capacity_and_hasher(nodes: usize, edges: usize, hasher: S) -> Self
219    where
220        S: Clone,
221    {
222        Self {
223            nodes: IndexMap::with_capacity_and_hasher(nodes, hasher.clone()),
224            edges: IndexMap::with_capacity_and_hasher(edges, hasher),
225            ty: PhantomData,
226        }
227    }
228
229    /// Return the current node and edge capacity of the graph.
230    pub fn capacity(&self) -> (usize, usize) {
231        (self.nodes.capacity(), self.edges.capacity())
232    }
233
234    /// Use their natural order to map the node pair (a, b) to a canonical edge id.
235    #[inline]
236    fn edge_key(a: N, b: N) -> (N, N) {
237        if Ty::is_directed() || a <= b {
238            (a, b)
239        } else {
240            (b, a)
241        }
242    }
243
244    /// Whether the graph has directed edges.
245    pub fn is_directed(&self) -> bool {
246        Ty::is_directed()
247    }
248
249    /// Create a new `GraphMap` from an iterable of edges.
250    ///
251    /// Node values are taken directly from the list.
252    /// Edge weights `E` may either be specified in the list,
253    /// or they are filled with default values.
254    ///
255    /// Nodes are inserted automatically to match the edges.
256    ///
257    /// ```
258    /// use petgraph::graphmap::UnGraphMap;
259    ///
260    /// // Create a new undirected GraphMap.
261    /// // Use a type hint to have `()` be the edge weight type.
262    /// let gr = UnGraphMap::<_, ()>::from_edges(&[
263    ///     (0, 1), (0, 2), (0, 3),
264    ///     (1, 2), (1, 3),
265    ///     (2, 3),
266    /// ]);
267    /// ```
268    pub fn from_edges<I>(iterable: I) -> Self
269    where
270        I: IntoIterator,
271        I::Item: IntoWeightedEdge<E, NodeId = N>,
272        S: Default,
273    {
274        Self::from_iter(iterable)
275    }
276
277    /// Return the number of nodes in the graph.
278    pub fn node_count(&self) -> usize {
279        self.nodes.len()
280    }
281
282    /// Return the number of edges in the graph.
283    pub fn edge_count(&self) -> usize {
284        self.edges.len()
285    }
286
287    /// Remove all nodes and edges
288    pub fn clear(&mut self) {
289        self.nodes.clear();
290        self.edges.clear();
291    }
292
293    /// Add node `n` to the graph.
294    pub fn add_node(&mut self, n: N) -> N {
295        self.nodes.entry(n).or_default();
296        n
297    }
298
299    /// Remove node `n` from the graph.
300    ///
301    /// Return `true` if it did exist.
302    ///
303    /// Computes in **O(V)** time, due to the removal of edges with other nodes.
304    pub fn remove_node(&mut self, n: N) -> bool {
305        let links = match self.nodes.swap_remove(&n) {
306            None => return false,
307            Some(sus) => sus,
308        };
309        for (succ, dir) in links {
310            let edge = if dir == CompactDirection::Outgoing {
311                Self::edge_key(n, succ)
312            } else {
313                Self::edge_key(succ, n)
314            };
315            // remove all successor links
316            self.remove_single_edge(&succ, &n, dir.opposite());
317            // Remove all edge values
318            self.edges.swap_remove(&edge);
319        }
320        true
321    }
322
323    /// Return `true` if the node is contained in the graph.
324    pub fn contains_node(&self, n: N) -> bool {
325        self.nodes.contains_key(&n)
326    }
327
328    /// Add an edge connecting `a` and `b` to the graph, with associated
329    /// data `weight`. For a directed graph, the edge is directed from `a`
330    /// to `b`.
331    ///
332    /// Inserts nodes `a` and/or `b` if they aren't already part of the graph.
333    ///
334    /// Return `None` if the edge did not previously exist, otherwise,
335    /// the associated data is updated and the old value is returned
336    /// as `Some(old_weight)`.
337    ///
338    /// ```
339    /// // Create a GraphMap with directed edges, and add one edge to it
340    /// use petgraph::graphmap::DiGraphMap;
341    ///
342    /// let mut g = DiGraphMap::<_, _>::new();
343    /// g.add_edge("x", "y", -1);
344    /// assert_eq!(g.node_count(), 2);
345    /// assert_eq!(g.edge_count(), 1);
346    /// assert!(g.contains_edge("x", "y"));
347    /// assert!(!g.contains_edge("y", "x"));
348    /// ```
349    pub fn add_edge(&mut self, a: N, b: N, weight: E) -> Option<E> {
350        if let old @ Some(_) = self.edges.insert(Self::edge_key(a, b), weight) {
351            old
352        } else {
353            // insert in the adjacency list if it's a new edge
354            self.nodes
355                .entry(a)
356                .or_insert_with(|| Vec::with_capacity(1))
357                .push((b, CompactDirection::Outgoing));
358            if a != b {
359                // self loops don't have the Incoming entry
360                self.nodes
361                    .entry(b)
362                    .or_insert_with(|| Vec::with_capacity(1))
363                    .push((a, CompactDirection::Incoming));
364            }
365            None
366        }
367    }
368
369    /// Remove edge relation from a to b
370    ///
371    /// Return `true` if it did exist.
372    fn remove_single_edge(&mut self, a: &N, b: &N, dir: CompactDirection) -> bool {
373        match self.nodes.get_mut(a) {
374            None => false,
375            Some(sus) => {
376                if Ty::is_directed() {
377                    match sus.iter().position(|elt| elt == &(*b, dir)) {
378                        Some(index) => {
379                            sus.swap_remove(index);
380                            true
381                        }
382                        None => false,
383                    }
384                } else {
385                    match sus.iter().position(|elt| &elt.0 == b) {
386                        Some(index) => {
387                            sus.swap_remove(index);
388                            true
389                        }
390                        None => false,
391                    }
392                }
393            }
394        }
395    }
396
397    /// Remove edge from `a` to `b` from the graph and return the edge weight.
398    ///
399    /// Return `None` if the edge didn't exist.
400    ///
401    /// ```
402    /// // Create a GraphMap with undirected edges, and add and remove an edge.
403    /// use petgraph::graphmap::UnGraphMap;
404    ///
405    /// let mut g = UnGraphMap::<_, _>::new();
406    /// g.add_edge("x", "y", -1);
407    ///
408    /// let edge_data = g.remove_edge("y", "x");
409    /// assert_eq!(edge_data, Some(-1));
410    /// assert_eq!(g.edge_count(), 0);
411    /// ```
412    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E> {
413        let exist1 = self.remove_single_edge(&a, &b, CompactDirection::Outgoing);
414        let exist2 = if a != b {
415            self.remove_single_edge(&b, &a, CompactDirection::Incoming)
416        } else {
417            exist1
418        };
419        let weight = self.edges.swap_remove(&Self::edge_key(a, b));
420        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
421        weight
422    }
423
424    /// Return `true` if the edge connecting `a` with `b` is contained in the graph.
425    pub fn contains_edge(&self, a: N, b: N) -> bool {
426        self.edges.contains_key(&Self::edge_key(a, b))
427    }
428
429    /// Return an iterator over the nodes of the graph.
430    ///
431    /// Iterator element type is `N`.
432    pub fn nodes(&self) -> Nodes<'_, N> {
433        Nodes {
434            iter: self.nodes.keys().copied(),
435        }
436    }
437
438    /// Return a parallel iterator over the nodes of the graph.
439    ///
440    /// Iterator element type is `N`.
441    #[cfg(feature = "rayon")]
442    pub fn par_nodes(&self) -> ParNodes<'_, N>
443    where
444        N: Send + Sync,
445    {
446        ParNodes {
447            iter: self.nodes.par_keys(),
448        }
449    }
450
451    /// Return an iterator of all nodes with an edge starting from `a`.
452    ///
453    /// - `Directed`: Outgoing edges from `a`.
454    /// - `Undirected`: All edges from or to `a`.
455    ///
456    /// Produces an empty iterator if the node doesn't exist.<br>
457    /// Iterator element type is `N`.
458    pub fn neighbors(&self, a: N) -> Neighbors<N, Ty> {
459        Neighbors {
460            iter: match self.nodes.get(&a) {
461                Some(neigh) => neigh.iter(),
462                None => [].iter(),
463            },
464            ty: self.ty,
465        }
466    }
467
468    /// Return an iterator of all neighbors that have an edge between them and
469    /// `a`, in the specified direction.
470    /// If the graph's edges are undirected, this is equivalent to *.neighbors(a)*.
471    ///
472    /// - `Directed`, `Outgoing`: All edges from `a`.
473    /// - `Directed`, `Incoming`: All edges to `a`.
474    /// - `Undirected`: All edges from or to `a`.
475    ///
476    /// Produces an empty iterator if the node doesn't exist.<br>
477    /// Iterator element type is `N`.
478    pub fn neighbors_directed(&self, a: N, dir: Direction) -> NeighborsDirected<N, Ty> {
479        NeighborsDirected {
480            iter: match self.nodes.get(&a) {
481                Some(neigh) => neigh.iter(),
482                None => [].iter(),
483            },
484            start_node: a,
485            dir,
486            ty: self.ty,
487        }
488    }
489
490    /// Return an iterator of target nodes with an edge starting from `a`,
491    /// paired with their respective edge weights.
492    ///
493    /// - `Directed`: Outgoing edges from `a`.
494    /// - `Undirected`: All edges from or to `a`.
495    ///
496    /// Produces an empty iterator if the node doesn't exist.<br>
497    /// Iterator element type is `(N, N, &E)`.
498    pub fn edges(&self, a: N) -> Edges<N, E, Ty, S> {
499        Edges {
500            from: a,
501            iter: self.neighbors(a),
502            edges: &self.edges,
503        }
504    }
505
506    /// Return an iterator of target nodes with an edge starting from `a`,
507    /// paired with their respective edge weights.
508    ///
509    /// - `Directed`, `Outgoing`: All edges from `a`.
510    /// - `Directed`, `Incoming`: All edges to `a`.
511    /// - `Undirected`, `Outgoing`: All edges connected to `a`, with `a` being the source of each
512    ///   edge.
513    /// - `Undirected`, `Incoming`: All edges connected to `a`, with `a` being the target of each
514    ///   edge.
515    ///
516    /// Produces an empty iterator if the node doesn't exist.<br>
517    /// Iterator element type is `(N, N, &E)`.
518    pub fn edges_directed(&self, a: N, dir: Direction) -> EdgesDirected<N, E, Ty, S> {
519        EdgesDirected {
520            from: a,
521            iter: self.neighbors_directed(a, dir),
522            dir,
523            edges: &self.edges,
524        }
525    }
526
527    /// Return a reference to the edge weight connecting `a` with `b`, or
528    /// `None` if the edge does not exist in the graph.
529    pub fn edge_weight(&self, a: N, b: N) -> Option<&E> {
530        self.edges.get(&Self::edge_key(a, b))
531    }
532
533    /// Return a mutable reference to the edge weight connecting `a` with `b`, or
534    /// `None` if the edge does not exist in the graph.
535    pub fn edge_weight_mut(&mut self, a: N, b: N) -> Option<&mut E> {
536        self.edges.get_mut(&Self::edge_key(a, b))
537    }
538
539    /// Return an iterator over all edges of the graph with their weight in arbitrary order.
540    ///
541    /// Iterator element type is `(N, N, &E)`
542    pub fn all_edges(&self) -> AllEdges<N, E, Ty> {
543        AllEdges {
544            inner: self.edges.iter(),
545            ty: self.ty,
546        }
547    }
548
549    /// Return an iterator over all edges of the graph in arbitrary order, with a mutable reference
550    /// to their weight.
551    ///
552    /// Iterator element type is `(N, N, &mut E)`
553    pub fn all_edges_mut(&mut self) -> AllEdgesMut<N, E, Ty> {
554        AllEdgesMut {
555            inner: self.edges.iter_mut(),
556            ty: self.ty,
557        }
558    }
559
560    /// Return a parallel iterator over all edges of the graph with their weight in arbitrary
561    /// order.
562    ///
563    /// Iterator element type is `(N, N, &E)`
564    #[cfg(feature = "rayon")]
565    pub fn par_all_edges(&self) -> ParAllEdges<N, E, Ty>
566    where
567        N: Send + Sync,
568        E: Sync,
569    {
570        ParAllEdges {
571            inner: self.edges.par_iter(),
572            ty: PhantomData,
573        }
574    }
575
576    /// Return a parallel iterator over all edges of the graph in arbitrary order, with a mutable
577    /// reference to their weight.
578    ///
579    /// Iterator element type is `(N, N, &mut E)`
580    #[cfg(feature = "rayon")]
581    pub fn par_all_edges_mut(&mut self) -> ParAllEdgesMut<N, E, Ty>
582    where
583        N: Send + Sync,
584        E: Send,
585    {
586        ParAllEdgesMut {
587            inner: self.edges.par_iter_mut(),
588            ty: PhantomData,
589        }
590    }
591
592    /// Return a `Graph` that corresponds to this `GraphMap`.
593    ///
594    /// 1. Note that node and edge indices in the `Graph` have nothing in common
595    ///    with the `GraphMap`s node weights `N`. The node weights `N` are used as
596    ///    node weights in the resulting `Graph`, too.
597    /// 2. Note that the index type is user-chosen.
598    ///
599    /// Computes in **O(|V| + |E|)** time (average) where V is the set of nodes and E is the set of edges.
600    ///
601    /// **Panics** if the number of nodes or edges does not fit with
602    /// the resulting graph's index type.
603    #[track_caller]
604    pub fn into_graph<Ix>(self) -> Graph<N, E, Ty, Ix>
605    where
606        Ix: crate::graph::IndexType,
607    {
608        // assuming two successive iterations of the same hashmap produce the same order
609        let mut gr = Graph::with_capacity(self.node_count(), self.edge_count());
610        for (&node, _) in &self.nodes {
611            gr.add_node(node);
612        }
613        for ((a, b), edge_weight) in self.edges {
614            let ai = self.nodes.get_index_of(&a).unwrap();
615            let bi = self.nodes.get_index_of(&b).unwrap();
616            gr.add_edge(node_index(ai), node_index(bi), edge_weight);
617        }
618        gr
619    }
620
621    /// Creates a `GraphMap` that corresponds to the given `Graph`.
622    ///
623    /// **Warning**: Nodes with the same weight are merged and only the last parallel edge
624    /// is kept. Node and edge indices of the `Graph` are lost. Only use this function
625    /// if the node weights are distinct and there are no parallel edges.
626    ///
627    /// Computes in **O(|V| + |E|)** time (average).
628    pub fn from_graph<Ix>(graph: Graph<N, E, Ty, Ix>) -> Self
629    where
630        Ix: crate::graph::IndexType,
631        E: Clone,
632        S: Default,
633    {
634        let mut new_graph: GraphMap<N, E, Ty, S> =
635            GraphMap::with_capacity(graph.node_count(), graph.edge_count());
636
637        for node in graph.raw_nodes() {
638            new_graph.add_node(node.weight);
639        }
640
641        for edge in graph.edge_indices() {
642            let (a, b) = graph.edge_endpoints(edge).unwrap();
643            new_graph.add_edge(
644                *graph.node_weight(a).unwrap(),
645                *graph.node_weight(b).unwrap(),
646                graph.edge_weight(edge).unwrap().clone(),
647            );
648        }
649
650        new_graph
651    }
652}
653
654/// Create a new `GraphMap` from an iterable of edges.
655impl<N, E, Ty, Item, S> FromIterator<Item> for GraphMap<N, E, Ty, S>
656where
657    Item: IntoWeightedEdge<E, NodeId = N>,
658    N: NodeTrait,
659    Ty: EdgeType,
660    S: BuildHasher + Default,
661{
662    fn from_iter<I>(iterable: I) -> Self
663    where
664        I: IntoIterator<Item = Item>,
665    {
666        let iter = iterable.into_iter();
667        let (low, _) = iter.size_hint();
668        let mut g = Self::with_capacity(0, low);
669        g.extend(iter);
670        g
671    }
672}
673
674/// Extend the graph from an iterable of edges.
675///
676/// Nodes are inserted automatically to match the edges.
677impl<N, E, Ty, Item, S> Extend<Item> for GraphMap<N, E, Ty, S>
678where
679    Item: IntoWeightedEdge<E, NodeId = N>,
680    N: NodeTrait,
681    Ty: EdgeType,
682    S: BuildHasher,
683{
684    fn extend<I>(&mut self, iterable: I)
685    where
686        I: IntoIterator<Item = Item>,
687    {
688        let iter = iterable.into_iter();
689        let (low, _) = iter.size_hint();
690        self.edges.reserve(low);
691
692        for elt in iter {
693            let (source, target, weight) = elt.into_weighted_edge();
694            self.add_edge(source, target, weight);
695        }
696    }
697}
698
699iterator_wrap! {
700    impl (Iterator DoubleEndedIterator ExactSizeIterator) for
701    #[derive(Debug, Clone)]
702    struct Nodes <'a, N> where { N: 'a + NodeTrait }
703    item: N,
704    iter: Copied<Keys<'a, N, Vec<(N, CompactDirection)>>>,
705}
706
707#[derive(Debug, Clone)]
708pub struct Neighbors<'a, N, Ty = Undirected>
709where
710    N: 'a,
711    Ty: EdgeType,
712{
713    iter: Iter<'a, (N, CompactDirection)>,
714    ty: PhantomData<Ty>,
715}
716
717impl<N, Ty> Iterator for Neighbors<'_, N, Ty>
718where
719    N: NodeTrait,
720    Ty: EdgeType,
721{
722    type Item = N;
723    fn next(&mut self) -> Option<N> {
724        if Ty::is_directed() {
725            (&mut self.iter)
726                .filter_map(|&(n, dir)| if dir == Outgoing { Some(n) } else { None })
727                .next()
728        } else {
729            self.iter.next().map(|&(n, _)| n)
730        }
731    }
732    fn size_hint(&self) -> (usize, Option<usize>) {
733        let (lower, upper) = self.iter.size_hint();
734        if Ty::is_directed() {
735            (0, upper)
736        } else {
737            (lower, upper)
738        }
739    }
740}
741
742#[derive(Debug, Clone)]
743pub struct NeighborsDirected<'a, N, Ty>
744where
745    N: 'a,
746    Ty: EdgeType,
747{
748    iter: Iter<'a, (N, CompactDirection)>,
749    start_node: N,
750    dir: Direction,
751    ty: PhantomData<Ty>,
752}
753
754impl<N, Ty> Iterator for NeighborsDirected<'_, N, Ty>
755where
756    N: NodeTrait,
757    Ty: EdgeType,
758{
759    type Item = N;
760    fn next(&mut self) -> Option<N> {
761        if Ty::is_directed() {
762            let self_dir = self.dir;
763            let start_node = self.start_node;
764            (&mut self.iter)
765                .filter_map(move |&(n, dir)| {
766                    if dir == self_dir || n == start_node {
767                        Some(n)
768                    } else {
769                        None
770                    }
771                })
772                .next()
773        } else {
774            self.iter.next().map(|&(n, _)| n)
775        }
776    }
777    fn size_hint(&self) -> (usize, Option<usize>) {
778        let (lower, upper) = self.iter.size_hint();
779        if Ty::is_directed() {
780            (0, upper)
781        } else {
782            (lower, upper)
783        }
784    }
785}
786
787#[derive(Debug, Clone)]
788pub struct Edges<
789    'a,
790    N,
791    E: 'a,
792    Ty,
793    #[cfg(not(feature = "std"))] S,
794    #[cfg(feature = "std")] S = RandomState,
795> where
796    N: 'a + NodeTrait,
797    Ty: EdgeType,
798    S: BuildHasher,
799{
800    from: N,
801    edges: &'a IndexMap<(N, N), E, S>,
802    iter: Neighbors<'a, N, Ty>,
803}
804
805impl<'a, N, E, Ty, S> Iterator for Edges<'a, N, E, Ty, S>
806where
807    N: 'a + NodeTrait,
808    E: 'a,
809    Ty: EdgeType,
810    S: BuildHasher,
811{
812    type Item = (N, N, &'a E);
813    fn next(&mut self) -> Option<Self::Item> {
814        self.iter.next().map(|b| {
815            let a = self.from;
816            match self.edges.get(&GraphMap::<N, E, Ty, S>::edge_key(a, b)) {
817                None => unreachable!(),
818                Some(edge) => (a, b, edge),
819            }
820        })
821    }
822    fn size_hint(&self) -> (usize, Option<usize>) {
823        self.iter.size_hint()
824    }
825}
826
827#[derive(Debug, Clone)]
828pub struct EdgesDirected<
829    'a,
830    N,
831    E: 'a,
832    Ty,
833    #[cfg(not(feature = "std"))] S,
834    #[cfg(feature = "std")] S = RandomState,
835> where
836    N: 'a + NodeTrait,
837    Ty: EdgeType,
838    S: BuildHasher,
839{
840    from: N,
841    dir: Direction,
842    edges: &'a IndexMap<(N, N), E, S>,
843    iter: NeighborsDirected<'a, N, Ty>,
844}
845
846impl<'a, N, E, Ty, S> Iterator for EdgesDirected<'a, N, E, Ty, S>
847where
848    N: 'a + NodeTrait,
849    E: 'a,
850    Ty: EdgeType,
851    S: BuildHasher,
852{
853    type Item = (N, N, &'a E);
854    fn next(&mut self) -> Option<Self::Item> {
855        self.iter.next().map(|mut b| {
856            let mut a = self.from;
857            if self.dir == Direction::Incoming {
858                mem::swap(&mut a, &mut b);
859            }
860            match self.edges.get(&GraphMap::<N, E, Ty, S>::edge_key(a, b)) {
861                None => unreachable!(),
862                Some(edge) => (a, b, edge),
863            }
864        })
865    }
866    fn size_hint(&self) -> (usize, Option<usize>) {
867        self.iter.size_hint()
868    }
869}
870
871#[derive(Debug, Clone)]
872pub struct AllEdges<'a, N, E: 'a, Ty>
873where
874    N: 'a + NodeTrait,
875{
876    inner: IndexMapIter<'a, (N, N), E>,
877    ty: PhantomData<Ty>,
878}
879
880impl<'a, N, E, Ty> Iterator for AllEdges<'a, N, E, Ty>
881where
882    N: 'a + NodeTrait,
883    E: 'a,
884    Ty: EdgeType,
885{
886    type Item = (N, N, &'a E);
887    fn next(&mut self) -> Option<Self::Item> {
888        self.inner.next().map(|(&(a, b), v)| (a, b, v))
889    }
890
891    fn size_hint(&self) -> (usize, Option<usize>) {
892        self.inner.size_hint()
893    }
894
895    fn count(self) -> usize {
896        self.inner.count()
897    }
898
899    fn nth(&mut self, n: usize) -> Option<Self::Item> {
900        self.inner
901            .nth(n)
902            .map(|(&(n1, n2), weight)| (n1, n2, weight))
903    }
904
905    fn last(self) -> Option<Self::Item> {
906        self.inner
907            .last()
908            .map(|(&(n1, n2), weight)| (n1, n2, weight))
909    }
910}
911
912impl<'a, N, E, Ty> DoubleEndedIterator for AllEdges<'a, N, E, Ty>
913where
914    N: 'a + NodeTrait,
915    E: 'a,
916    Ty: EdgeType,
917{
918    fn next_back(&mut self) -> Option<Self::Item> {
919        self.inner
920            .next_back()
921            .map(|(&(n1, n2), weight)| (n1, n2, weight))
922    }
923}
924
925pub struct AllEdgesMut<'a, N, E: 'a, Ty>
926where
927    N: 'a + NodeTrait,
928{
929    inner: IndexMapIterMut<'a, (N, N), E>, // TODO: change to something that implements Debug + Clone?
930    ty: PhantomData<Ty>,
931}
932
933impl<'a, N, E, Ty> Iterator for AllEdgesMut<'a, N, E, Ty>
934where
935    N: 'a + NodeTrait,
936    E: 'a,
937    Ty: EdgeType,
938{
939    type Item = (N, N, &'a mut E);
940    fn next(&mut self) -> Option<Self::Item> {
941        self.inner
942            .next()
943            .map(|(&(n1, n2), weight)| (n1, n2, weight))
944    }
945
946    fn size_hint(&self) -> (usize, Option<usize>) {
947        self.inner.size_hint()
948    }
949
950    fn count(self) -> usize {
951        self.inner.count()
952    }
953
954    fn nth(&mut self, n: usize) -> Option<Self::Item> {
955        self.inner
956            .nth(n)
957            .map(|(&(n1, n2), weight)| (n1, n2, weight))
958    }
959
960    fn last(self) -> Option<Self::Item> {
961        self.inner
962            .last()
963            .map(|(&(n1, n2), weight)| (n1, n2, weight))
964    }
965}
966
967impl<'a, N, E, Ty> DoubleEndedIterator for AllEdgesMut<'a, N, E, Ty>
968where
969    N: 'a + NodeTrait,
970    E: 'a,
971    Ty: EdgeType,
972{
973    fn next_back(&mut self) -> Option<Self::Item> {
974        self.inner
975            .next_back()
976            .map(|(&(n1, n2), weight)| (n1, n2, weight))
977    }
978}
979
980/// Index `GraphMap` by node pairs to access edge weights.
981impl<N, E, Ty, S> Index<(N, N)> for GraphMap<N, E, Ty, S>
982where
983    N: NodeTrait,
984    Ty: EdgeType,
985    S: BuildHasher,
986{
987    type Output = E;
988    fn index(&self, index: (N, N)) -> &E {
989        let index = Self::edge_key(index.0, index.1);
990        self.edge_weight(index.0, index.1)
991            .expect("GraphMap::index: no such edge")
992    }
993}
994
995/// Index `GraphMap` by node pairs to access edge weights.
996impl<N, E, Ty, S> IndexMut<(N, N)> for GraphMap<N, E, Ty, S>
997where
998    N: NodeTrait,
999    Ty: EdgeType,
1000    S: BuildHasher,
1001{
1002    fn index_mut(&mut self, index: (N, N)) -> &mut E {
1003        let index = Self::edge_key(index.0, index.1);
1004        self.edge_weight_mut(index.0, index.1)
1005            .expect("GraphMap::index: no such edge")
1006    }
1007}
1008
1009/// Create a new empty `GraphMap`.
1010impl<N, E, Ty, S> Default for GraphMap<N, E, Ty, S>
1011where
1012    N: NodeTrait,
1013    Ty: EdgeType,
1014    S: BuildHasher + Default,
1015{
1016    fn default() -> Self {
1017        GraphMap::with_capacity(0, 0)
1018    }
1019}
1020
1021/// A reference that is hashed and compared by its pointer value.
1022///
1023/// `Ptr` is used for certain configurations of `GraphMap`,
1024/// in particular in the combination where the node type for
1025/// `GraphMap` is something of type for example `Ptr(&Cell<T>)`,
1026/// with the `Cell<T>` being `TypedArena` allocated.
1027pub struct Ptr<'b, T: 'b>(pub &'b T);
1028
1029impl<T> Copy for Ptr<'_, T> {}
1030impl<T> Clone for Ptr<'_, T> {
1031    fn clone(&self) -> Self {
1032        *self
1033    }
1034}
1035
1036fn ptr_eq<T>(a: *const T, b: *const T) -> bool {
1037    a == b
1038}
1039
1040impl<'b, T> PartialEq for Ptr<'b, T> {
1041    /// Ptr compares by pointer equality, i.e if they point to the same value
1042    fn eq(&self, other: &Ptr<'b, T>) -> bool {
1043        ptr_eq(self.0, other.0)
1044    }
1045}
1046
1047impl<'b, T> PartialOrd for Ptr<'b, T> {
1048    fn partial_cmp(&self, other: &Ptr<'b, T>) -> Option<Ordering> {
1049        Some(self.cmp(other))
1050    }
1051}
1052
1053impl<'b, T> Ord for Ptr<'b, T> {
1054    /// Ptr is ordered by pointer value, i.e. an arbitrary but stable and total order.
1055    fn cmp(&self, other: &Ptr<'b, T>) -> Ordering {
1056        let a: *const T = self.0;
1057        let b: *const T = other.0;
1058        a.cmp(&b)
1059    }
1060}
1061
1062impl<T> Deref for Ptr<'_, T> {
1063    type Target = T;
1064    fn deref(&self) -> &T {
1065        self.0
1066    }
1067}
1068
1069impl<T> Eq for Ptr<'_, T> {}
1070
1071impl<T> Hash for Ptr<'_, T> {
1072    fn hash<H: hash::Hasher>(&self, st: &mut H) {
1073        let ptr = (self.0) as *const T;
1074        ptr.hash(st)
1075    }
1076}
1077
1078impl<T: fmt::Debug> fmt::Debug for Ptr<'_, T> {
1079    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1080        self.0.fmt(f)
1081    }
1082}
1083
1084#[derive(Debug, Clone)]
1085pub struct NodeIdentifiers<'a, N, E: 'a, Ty>
1086where
1087    N: 'a + NodeTrait,
1088{
1089    iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>,
1090    ty: PhantomData<Ty>,
1091    edge_ty: PhantomData<E>,
1092}
1093
1094impl<'a, N, E, Ty> Iterator for NodeIdentifiers<'a, N, E, Ty>
1095where
1096    N: 'a + NodeTrait,
1097    E: 'a,
1098    Ty: EdgeType,
1099{
1100    type Item = N;
1101    fn next(&mut self) -> Option<Self::Item> {
1102        self.iter.next().map(|(&n, _)| n)
1103    }
1104    fn size_hint(&self) -> (usize, Option<usize>) {
1105        self.iter.size_hint()
1106    }
1107}
1108
1109#[derive(Debug, Clone)]
1110pub struct NodeReferences<'a, N, E: 'a, Ty>
1111where
1112    N: 'a + NodeTrait,
1113{
1114    iter: IndexMapIter<'a, N, Vec<(N, CompactDirection)>>,
1115    ty: PhantomData<Ty>,
1116    edge_ty: PhantomData<E>,
1117}
1118
1119impl<'a, N, E, Ty> Iterator for NodeReferences<'a, N, E, Ty>
1120where
1121    N: 'a + NodeTrait,
1122    E: 'a,
1123    Ty: EdgeType,
1124{
1125    type Item = (N, &'a N);
1126    fn next(&mut self) -> Option<Self::Item> {
1127        self.iter.next().map(|(n, _)| (*n, n))
1128    }
1129    fn size_hint(&self) -> (usize, Option<usize>) {
1130        self.iter.size_hint()
1131    }
1132}
1133
1134impl<N, E, Ty, S> visit::GraphBase for GraphMap<N, E, Ty, S>
1135where
1136    N: Copy + PartialEq,
1137    S: BuildHasher,
1138{
1139    type NodeId = N;
1140    type EdgeId = (N, N);
1141}
1142
1143impl<N, E, Ty, S> visit::Data for GraphMap<N, E, Ty, S>
1144where
1145    N: Copy + PartialEq,
1146    Ty: EdgeType,
1147    S: BuildHasher,
1148{
1149    type NodeWeight = N;
1150    type EdgeWeight = E;
1151}
1152
1153impl<N, E, Ty, S> visit::Visitable for GraphMap<N, E, Ty, S>
1154where
1155    N: Copy + Ord + Hash,
1156    Ty: EdgeType,
1157    S: BuildHasher,
1158{
1159    type Map = HashSet<N>;
1160    fn visit_map(&self) -> HashSet<N> {
1161        HashSet::with_capacity(self.node_count())
1162    }
1163    fn reset_map(&self, map: &mut Self::Map) {
1164        map.clear();
1165    }
1166}
1167
1168impl<N, E, Ty, S> visit::GraphProp for GraphMap<N, E, Ty, S>
1169where
1170    N: NodeTrait,
1171    Ty: EdgeType,
1172    S: BuildHasher,
1173{
1174    type EdgeType = Ty;
1175}
1176
1177impl<'a, N, E, Ty, S> visit::IntoNodeReferences for &'a GraphMap<N, E, Ty, S>
1178where
1179    N: NodeTrait,
1180    Ty: EdgeType,
1181    S: BuildHasher,
1182{
1183    type NodeRef = (N, &'a N);
1184    type NodeReferences = NodeReferences<'a, N, E, Ty>;
1185    fn node_references(self) -> Self::NodeReferences {
1186        NodeReferences {
1187            iter: self.nodes.iter(),
1188            ty: self.ty,
1189            edge_ty: PhantomData,
1190        }
1191    }
1192}
1193
1194impl<'a, N, E: 'a, Ty, S> visit::IntoNodeIdentifiers for &'a GraphMap<N, E, Ty, S>
1195where
1196    N: NodeTrait,
1197    Ty: EdgeType,
1198    S: BuildHasher,
1199{
1200    type NodeIdentifiers = NodeIdentifiers<'a, N, E, Ty>;
1201
1202    fn node_identifiers(self) -> Self::NodeIdentifiers {
1203        NodeIdentifiers {
1204            iter: self.nodes.iter(),
1205            ty: self.ty,
1206            edge_ty: PhantomData,
1207        }
1208    }
1209}
1210
1211impl<N, E, Ty, S> visit::NodeCount for GraphMap<N, E, Ty, S>
1212where
1213    N: NodeTrait,
1214    Ty: EdgeType,
1215    S: BuildHasher,
1216{
1217    fn node_count(&self) -> usize {
1218        (*self).node_count()
1219    }
1220}
1221
1222impl<N, E, Ty, S> visit::NodeIndexable for GraphMap<N, E, Ty, S>
1223where
1224    N: NodeTrait,
1225    Ty: EdgeType,
1226    S: BuildHasher,
1227{
1228    fn node_bound(&self) -> usize {
1229        self.node_count()
1230    }
1231    fn to_index(&self, ix: Self::NodeId) -> usize {
1232        self.nodes.get_index_of(&ix).expect("node not found")
1233    }
1234    fn from_index(&self, ix: usize) -> Self::NodeId {
1235        assert!(
1236            ix < self.nodes.len(),
1237            "The requested index {} is out-of-bounds.",
1238            ix
1239        );
1240        let (&key, _) = self.nodes.get_index(ix).unwrap();
1241        key
1242    }
1243}
1244
1245impl<N, E, Ty, S> visit::NodeCompactIndexable for GraphMap<N, E, Ty, S>
1246where
1247    N: NodeTrait,
1248    Ty: EdgeType,
1249    S: BuildHasher,
1250{
1251}
1252
1253impl<'a, N: 'a, E, Ty, S> visit::IntoNeighbors for &'a GraphMap<N, E, Ty, S>
1254where
1255    N: Copy + Ord + Hash,
1256    Ty: EdgeType,
1257    S: BuildHasher,
1258{
1259    type Neighbors = Neighbors<'a, N, Ty>;
1260    fn neighbors(self, n: Self::NodeId) -> Self::Neighbors {
1261        self.neighbors(n)
1262    }
1263}
1264
1265impl<'a, N: 'a, E, Ty, S> visit::IntoNeighborsDirected for &'a GraphMap<N, E, Ty, S>
1266where
1267    N: Copy + Ord + Hash,
1268    Ty: EdgeType,
1269    S: BuildHasher,
1270{
1271    type NeighborsDirected = NeighborsDirected<'a, N, Ty>;
1272    fn neighbors_directed(self, n: N, dir: Direction) -> Self::NeighborsDirected {
1273        self.neighbors_directed(n, dir)
1274    }
1275}
1276
1277impl<N, E, Ty, S> visit::EdgeIndexable for GraphMap<N, E, Ty, S>
1278where
1279    N: NodeTrait,
1280    Ty: EdgeType,
1281    S: BuildHasher,
1282{
1283    fn edge_bound(&self) -> usize {
1284        self.edge_count()
1285    }
1286
1287    fn to_index(&self, ix: Self::EdgeId) -> usize {
1288        self.edges.get_index_of(&ix).expect("edge not found")
1289    }
1290
1291    fn from_index(&self, ix: usize) -> Self::EdgeId {
1292        assert!(
1293            ix < self.edges.len(),
1294            "The requested index {} is out-of-bounds.",
1295            ix
1296        );
1297        let (&key, _) = self.edges.get_index(ix).unwrap();
1298        key
1299    }
1300}
1301
1302impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdges for &'a GraphMap<N, E, Ty, S>
1303where
1304    N: NodeTrait,
1305    Ty: EdgeType,
1306    S: BuildHasher,
1307{
1308    type Edges = Edges<'a, N, E, Ty, S>;
1309    fn edges(self, a: Self::NodeId) -> Self::Edges {
1310        self.edges(a)
1311    }
1312}
1313
1314impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdgesDirected for &'a GraphMap<N, E, Ty, S>
1315where
1316    N: NodeTrait,
1317    Ty: EdgeType,
1318    S: BuildHasher,
1319{
1320    type EdgesDirected = EdgesDirected<'a, N, E, Ty, S>;
1321    fn edges_directed(self, a: Self::NodeId, dir: Direction) -> Self::EdgesDirected {
1322        self.edges_directed(a, dir)
1323    }
1324}
1325
1326impl<'a, N: 'a, E: 'a, Ty, S> visit::IntoEdgeReferences for &'a GraphMap<N, E, Ty, S>
1327where
1328    N: NodeTrait,
1329    Ty: EdgeType,
1330    S: BuildHasher,
1331{
1332    type EdgeRef = (N, N, &'a E);
1333    type EdgeReferences = AllEdges<'a, N, E, Ty>;
1334    fn edge_references(self) -> Self::EdgeReferences {
1335        self.all_edges()
1336    }
1337}
1338
1339impl<N, E, Ty, S> visit::EdgeCount for GraphMap<N, E, Ty, S>
1340where
1341    N: NodeTrait,
1342    Ty: EdgeType,
1343    S: BuildHasher,
1344{
1345    #[inline]
1346    fn edge_count(&self) -> usize {
1347        self.edge_count()
1348    }
1349}
1350
1351/// The `GraphMap` keeps an adjacency matrix internally.
1352impl<N, E, Ty, S> visit::GetAdjacencyMatrix for GraphMap<N, E, Ty, S>
1353where
1354    N: Copy + Ord + Hash,
1355    Ty: EdgeType,
1356    S: BuildHasher,
1357{
1358    type AdjMatrix = ();
1359    #[inline]
1360    fn adjacency_matrix(&self) {}
1361    #[inline]
1362    fn is_adjacent(&self, _: &(), a: N, b: N) -> bool {
1363        self.contains_edge(a, b)
1364    }
1365}
1366
1367impl<N, E, Ty, S> data::DataMap for GraphMap<N, E, Ty, S>
1368where
1369    N: Copy + Ord + Hash,
1370    Ty: EdgeType,
1371    S: BuildHasher,
1372{
1373    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
1374        self.edge_weight(id.0, id.1)
1375    }
1376
1377    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
1378        // Technically `id` is already the weight for `GraphMap`, but since we need to return a reference, this is a O(1) borrowing alternative:
1379        self.nodes.get_key_value(&id).map(|(k, _)| k)
1380    }
1381}
1382
1383/// A [ParallelIterator] over this graph's nodes.
1384#[cfg(feature = "rayon")]
1385pub struct ParNodes<'a, N>
1386where
1387    N: NodeTrait + Send + Sync,
1388{
1389    iter: ParKeys<'a, N, Vec<(N, CompactDirection)>>,
1390}
1391
1392#[cfg(feature = "rayon")]
1393impl<N> ParallelIterator for ParNodes<'_, N>
1394where
1395    N: NodeTrait + Send + Sync,
1396{
1397    type Item = N;
1398
1399    fn drive_unindexed<C>(self, consumer: C) -> C::Result
1400    where
1401        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
1402    {
1403        self.iter.copied().drive_unindexed(consumer)
1404    }
1405
1406    fn opt_len(&self) -> Option<usize> {
1407        self.iter.opt_len()
1408    }
1409}
1410
1411#[cfg(feature = "rayon")]
1412impl<N> IndexedParallelIterator for ParNodes<'_, N>
1413where
1414    N: NodeTrait + Send + Sync,
1415{
1416    fn drive<C>(self, consumer: C) -> C::Result
1417    where
1418        C: rayon::iter::plumbing::Consumer<Self::Item>,
1419    {
1420        self.iter.copied().drive(consumer)
1421    }
1422
1423    fn len(&self) -> usize {
1424        self.iter.len()
1425    }
1426
1427    fn with_producer<CB>(self, callback: CB) -> CB::Output
1428    where
1429        CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
1430    {
1431        self.iter.copied().with_producer(callback)
1432    }
1433}
1434
1435/// A [ParallelIterator] over this graph's edges.
1436#[cfg(feature = "rayon")]
1437pub struct ParAllEdges<'a, N, E, Ty>
1438where
1439    N: NodeTrait + Send + Sync,
1440    E: Sync,
1441{
1442    inner: ParIter<'a, (N, N), E>,
1443    ty: PhantomData<fn(Ty)>,
1444}
1445
1446#[cfg(feature = "rayon")]
1447impl<'a, N, E, Ty> ParallelIterator for ParAllEdges<'a, N, E, Ty>
1448where
1449    N: NodeTrait + Send + Sync,
1450    E: Sync,
1451{
1452    type Item = (N, N, &'a E);
1453
1454    fn drive_unindexed<C>(self, c: C) -> C::Result
1455    where
1456        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
1457    {
1458        self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c)
1459    }
1460
1461    fn opt_len(&self) -> Option<usize> {
1462        self.inner.opt_len()
1463    }
1464}
1465
1466#[cfg(feature = "rayon")]
1467impl<N, E, Ty> IndexedParallelIterator for ParAllEdges<'_, N, E, Ty>
1468where
1469    N: NodeTrait + Send + Sync,
1470    E: Sync,
1471{
1472    fn drive<C>(self, consumer: C) -> C::Result
1473    where
1474        C: rayon::iter::plumbing::Consumer<Self::Item>,
1475    {
1476        self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer)
1477    }
1478
1479    fn len(&self) -> usize {
1480        self.inner.len()
1481    }
1482
1483    fn with_producer<CB>(self, callback: CB) -> CB::Output
1484    where
1485        CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
1486    {
1487        self.inner
1488            .map(|(&(a, b), v)| (a, b, v))
1489            .with_producer(callback)
1490    }
1491}
1492
1493/// A [ParallelIterator] over this graph's edges by mutable reference.
1494#[cfg(feature = "rayon")]
1495pub struct ParAllEdgesMut<'a, N, E: 'a, Ty>
1496where
1497    N: NodeTrait + Send + Sync,
1498    E: Send,
1499{
1500    inner: ParIterMut<'a, (N, N), E>,
1501    ty: PhantomData<fn(Ty)>,
1502}
1503
1504#[cfg(feature = "rayon")]
1505impl<'a, N, E, Ty> ParallelIterator for ParAllEdgesMut<'a, N, E, Ty>
1506where
1507    N: NodeTrait + Send + Sync,
1508    E: Send,
1509{
1510    type Item = (N, N, &'a mut E);
1511
1512    fn drive_unindexed<C>(self, c: C) -> C::Result
1513    where
1514        C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
1515    {
1516        self.inner.map(|(&(a, b), v)| (a, b, v)).drive_unindexed(c)
1517    }
1518
1519    fn opt_len(&self) -> Option<usize> {
1520        self.inner.opt_len()
1521    }
1522}
1523
1524#[cfg(feature = "rayon")]
1525impl<N, E, Ty> IndexedParallelIterator for ParAllEdgesMut<'_, N, E, Ty>
1526where
1527    N: NodeTrait + Send + Sync,
1528    E: Send,
1529{
1530    fn drive<C>(self, consumer: C) -> C::Result
1531    where
1532        C: rayon::iter::plumbing::Consumer<Self::Item>,
1533    {
1534        self.inner.map(|(&(a, b), v)| (a, b, v)).drive(consumer)
1535    }
1536
1537    fn len(&self) -> usize {
1538        self.inner.len()
1539    }
1540
1541    fn with_producer<CB>(self, callback: CB) -> CB::Output
1542    where
1543        CB: rayon::iter::plumbing::ProducerCallback<Self::Item>,
1544    {
1545        self.inner
1546            .map(|(&(a, b), v)| (a, b, v))
1547            .with_producer(callback)
1548    }
1549}