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