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