petgraph/
graphmap.rs

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