Coverage Report

Created: 2025-12-11 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/petgraph-0.8.3/src/data.rs
Line
Count
Source
1
//! Graph traits for associated data and graph construction.
2
3
use alloc::vec::Vec;
4
5
use crate::graph::IndexType;
6
use crate::visit::{Data, NodeCount, NodeIndexable, Reversed};
7
use crate::EdgeType;
8
use crate::Graph;
9
10
#[cfg(feature = "stable_graph")]
11
use crate::stable_graph::StableGraph;
12
13
#[cfg(feature = "graphmap")]
14
use {
15
    crate::graphmap::{GraphMap, NodeTrait},
16
    core::hash::BuildHasher,
17
};
18
19
trait_template! {
20
    /// Access node and edge weights (associated data).
21
#[allow(clippy::needless_arbitrary_self_type)]
22
pub trait DataMap : Data {
23
    @section self
24
    fn node_weight(self: &Self, id: Self::NodeId) -> Option<&Self::NodeWeight>;
25
    fn edge_weight(self: &Self, id: Self::EdgeId) -> Option<&Self::EdgeWeight>;
26
}
27
}
28
29
macro_rules! access0 {
30
    ($e:expr) => {
31
        $e.0
32
    };
33
}
34
35
DataMap! {delegate_impl []}
36
DataMap! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
37
DataMap! {delegate_impl [[G], G, Reversed<G>, access0]}
38
39
trait_template! {
40
    /// Access node and edge weights mutably.
41
#[allow(clippy::needless_arbitrary_self_type)]
42
pub trait DataMapMut : DataMap {
43
    @section self
44
    fn node_weight_mut(self: &mut Self, id: Self::NodeId) -> Option<&mut Self::NodeWeight>;
45
    fn edge_weight_mut(self: &mut Self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight>;
46
}
47
}
48
49
DataMapMut! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
50
DataMapMut! {delegate_impl [[G], G, Reversed<G>, access0]}
51
52
/// A graph that can be extended with further nodes and edges
53
pub trait Build: Data + NodeCount {
54
    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId;
55
    /// Add a new edge. If parallel edges (duplicate) are not allowed and
56
    /// the edge already exists, return `None`.
57
    ///
58
    /// Might panic if `a` or `b` are out of bounds.
59
    #[track_caller]
60
0
    fn add_edge(
61
0
        &mut self,
62
0
        a: Self::NodeId,
63
0
        b: Self::NodeId,
64
0
        weight: Self::EdgeWeight,
65
0
    ) -> Option<Self::EdgeId> {
66
0
        Some(self.update_edge(a, b, weight))
67
0
    }
68
    /// Add or update the edge from `a` to `b`. Return the id of the affected
69
    /// edge.
70
    ///
71
    /// Might panic if `a` or `b` are out of bounds.
72
    #[track_caller]
73
    fn update_edge(
74
        &mut self,
75
        a: Self::NodeId,
76
        b: Self::NodeId,
77
        weight: Self::EdgeWeight,
78
    ) -> Self::EdgeId;
79
}
80
81
/// A graph that can be created
82
pub trait Create: Build + Default {
83
    fn with_capacity(nodes: usize, edges: usize) -> Self;
84
}
85
86
impl<N, E, Ty, Ix> Data for Graph<N, E, Ty, Ix>
87
where
88
    Ix: IndexType,
89
{
90
    type NodeWeight = N;
91
    type EdgeWeight = E;
92
}
93
94
impl<N, E, Ty, Ix> DataMap for Graph<N, E, Ty, Ix>
95
where
96
    Ty: EdgeType,
97
    Ix: IndexType,
98
{
99
0
    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
100
0
        self.node_weight(id)
101
0
    }
102
0
    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
103
0
        self.edge_weight(id)
104
0
    }
105
}
106
107
impl<N, E, Ty, Ix> DataMapMut for Graph<N, E, Ty, Ix>
108
where
109
    Ty: EdgeType,
110
    Ix: IndexType,
111
{
112
0
    fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
113
0
        self.node_weight_mut(id)
114
0
    }
115
0
    fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
116
0
        self.edge_weight_mut(id)
117
0
    }
118
}
119
120
#[cfg(feature = "stable_graph")]
121
impl<N, E, Ty, Ix> DataMap for StableGraph<N, E, Ty, Ix>
122
where
123
    Ty: EdgeType,
124
    Ix: IndexType,
125
{
126
    fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
127
        self.node_weight(id)
128
    }
129
    fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
130
        self.edge_weight(id)
131
    }
132
}
133
134
#[cfg(feature = "stable_graph")]
135
impl<N, E, Ty, Ix> DataMapMut for StableGraph<N, E, Ty, Ix>
136
where
137
    Ty: EdgeType,
138
    Ix: IndexType,
139
{
140
    fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
141
        self.node_weight_mut(id)
142
    }
143
    fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
144
        self.edge_weight_mut(id)
145
    }
146
}
147
148
impl<N, E, Ty, Ix> Build for Graph<N, E, Ty, Ix>
149
where
150
    Ty: EdgeType,
151
    Ix: IndexType,
152
{
153
0
    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
154
0
        self.add_node(weight)
155
0
    }
156
0
    fn add_edge(
157
0
        &mut self,
158
0
        a: Self::NodeId,
159
0
        b: Self::NodeId,
160
0
        weight: Self::EdgeWeight,
161
0
    ) -> Option<Self::EdgeId> {
162
0
        Some(self.add_edge(a, b, weight))
163
0
    }
164
0
    fn update_edge(
165
0
        &mut self,
166
0
        a: Self::NodeId,
167
0
        b: Self::NodeId,
168
0
        weight: Self::EdgeWeight,
169
0
    ) -> Self::EdgeId {
170
0
        self.update_edge(a, b, weight)
171
0
    }
172
}
173
174
#[cfg(feature = "stable_graph")]
175
impl<N, E, Ty, Ix> Build for StableGraph<N, E, Ty, Ix>
176
where
177
    Ty: EdgeType,
178
    Ix: IndexType,
179
{
180
    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
181
        self.add_node(weight)
182
    }
183
    fn add_edge(
184
        &mut self,
185
        a: Self::NodeId,
186
        b: Self::NodeId,
187
        weight: Self::EdgeWeight,
188
    ) -> Option<Self::EdgeId> {
189
        Some(self.add_edge(a, b, weight))
190
    }
191
    fn update_edge(
192
        &mut self,
193
        a: Self::NodeId,
194
        b: Self::NodeId,
195
        weight: Self::EdgeWeight,
196
    ) -> Self::EdgeId {
197
        self.update_edge(a, b, weight)
198
    }
199
}
200
201
#[cfg(feature = "graphmap")]
202
impl<N, E, Ty, S> Build for GraphMap<N, E, Ty, S>
203
where
204
    Ty: EdgeType,
205
    N: NodeTrait,
206
    S: BuildHasher,
207
{
208
0
    fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
209
0
        self.add_node(weight)
210
0
    }
211
0
    fn add_edge(
212
0
        &mut self,
213
0
        a: Self::NodeId,
214
0
        b: Self::NodeId,
215
0
        weight: Self::EdgeWeight,
216
0
    ) -> Option<Self::EdgeId> {
217
0
        if self.contains_edge(a, b) {
218
0
            None
219
        } else {
220
0
            let r = self.add_edge(a, b, weight);
221
0
            debug_assert!(r.is_none());
222
0
            Some((a, b))
223
        }
224
0
    }
225
0
    fn update_edge(
226
0
        &mut self,
227
0
        a: Self::NodeId,
228
0
        b: Self::NodeId,
229
0
        weight: Self::EdgeWeight,
230
0
    ) -> Self::EdgeId {
231
0
        self.add_edge(a, b, weight);
232
0
        (a, b)
233
0
    }
234
}
235
236
impl<N, E, Ty, Ix> Create for Graph<N, E, Ty, Ix>
237
where
238
    Ty: EdgeType,
239
    Ix: IndexType,
240
{
241
0
    fn with_capacity(nodes: usize, edges: usize) -> Self {
242
0
        Self::with_capacity(nodes, edges)
243
0
    }
244
}
245
246
#[cfg(feature = "stable_graph")]
247
impl<N, E, Ty, Ix> Create for StableGraph<N, E, Ty, Ix>
248
where
249
    Ty: EdgeType,
250
    Ix: IndexType,
251
{
252
    fn with_capacity(nodes: usize, edges: usize) -> Self {
253
        Self::with_capacity(nodes, edges)
254
    }
255
}
256
257
#[cfg(feature = "graphmap")]
258
impl<N, E, Ty, S> Create for GraphMap<N, E, Ty, S>
259
where
260
    Ty: EdgeType,
261
    N: NodeTrait,
262
    S: BuildHasher + Default,
263
{
264
0
    fn with_capacity(nodes: usize, edges: usize) -> Self {
265
0
        Self::with_capacity(nodes, edges)
266
0
    }
267
}
268
269
/// A graph element.
270
///
271
/// A sequence of Elements, for example an iterator, is laid out as follows:
272
/// Nodes are implicitly given the index of their appearance in the sequence.
273
/// The edges’ source and target fields refer to these indices.
274
#[derive(Clone, Debug, PartialEq, Eq)]
275
pub enum Element<N, E> {
276
    /// A graph node.
277
    Node { weight: N },
278
    /// A graph edge.
279
    Edge {
280
        source: usize,
281
        target: usize,
282
        weight: E,
283
    },
284
}
285
286
/// Create a graph from an iterator of elements.
287
pub trait FromElements: Create {
288
0
    fn from_elements<I>(iterable: I) -> Self
289
0
    where
290
0
        Self: Sized,
291
0
        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
292
    {
293
0
        let mut gr = Self::with_capacity(0, 0);
294
        // usize -> NodeId map
295
0
        let mut map = Vec::new();
296
0
        for element in iterable {
297
0
            match element {
298
0
                Element::Node { weight } => {
299
0
                    map.push(gr.add_node(weight));
300
0
                }
301
                Element::Edge {
302
0
                    source,
303
0
                    target,
304
0
                    weight,
305
0
                } => {
306
0
                    gr.add_edge(map[source], map[target], weight);
307
0
                }
308
            }
309
        }
310
0
        gr
311
0
    }
312
}
313
314
0
fn from_elements_indexable<G, I>(iterable: I) -> G
315
0
where
316
0
    G: Create + NodeIndexable,
317
0
    I: IntoIterator<Item = Element<G::NodeWeight, G::EdgeWeight>>,
318
{
319
0
    let mut gr = G::with_capacity(0, 0);
320
0
    let map = |gr: &G, i| gr.from_index(i);
321
0
    for element in iterable {
322
0
        match element {
323
0
            Element::Node { weight } => {
324
0
                gr.add_node(weight);
325
0
            }
326
            Element::Edge {
327
0
                source,
328
0
                target,
329
0
                weight,
330
0
            } => {
331
0
                let from = map(&gr, source);
332
0
                let to = map(&gr, target);
333
0
                gr.add_edge(from, to, weight);
334
0
            }
335
        }
336
    }
337
0
    gr
338
0
}
339
340
impl<N, E, Ty, Ix> FromElements for Graph<N, E, Ty, Ix>
341
where
342
    Ty: EdgeType,
343
    Ix: IndexType,
344
{
345
0
    fn from_elements<I>(iterable: I) -> Self
346
0
    where
347
0
        Self: Sized,
348
0
        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
349
    {
350
0
        from_elements_indexable(iterable)
351
0
    }
352
}
353
354
#[cfg(feature = "stable_graph")]
355
impl<N, E, Ty, Ix> FromElements for StableGraph<N, E, Ty, Ix>
356
where
357
    Ty: EdgeType,
358
    Ix: IndexType,
359
{
360
    fn from_elements<I>(iterable: I) -> Self
361
    where
362
        Self: Sized,
363
        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
364
    {
365
        from_elements_indexable(iterable)
366
    }
367
}
368
369
#[cfg(feature = "graphmap")]
370
impl<N, E, Ty, S> FromElements for GraphMap<N, E, Ty, S>
371
where
372
    Ty: EdgeType,
373
    N: NodeTrait,
374
    S: BuildHasher + Default,
375
{
376
0
    fn from_elements<I>(iterable: I) -> Self
377
0
    where
378
0
        Self: Sized,
379
0
        I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
380
    {
381
0
        from_elements_indexable(iterable)
382
0
    }
383
}
384
385
/// Iterator adaptors for iterators of `Element`.
386
pub trait ElementIterator<N, E>: Iterator<Item = Element<N, E>> {
387
    /// Create an iterator adaptor that filters graph elements.
388
    ///
389
    /// The function `f` is called with each element and if its return value
390
    /// is `true` the element is accepted and if `false` it is removed.
391
    /// `f` is called with mutable references to the node and edge weights,
392
    /// so that they can be mutated (but the edge endpoints can not).
393
    ///
394
    /// This filter adapts the edge source and target indices in the
395
    /// stream so that they are correct after the removals.
396
0
    fn filter_elements<F>(self, f: F) -> FilterElements<Self, F>
397
0
    where
398
0
        Self: Sized,
399
0
        F: FnMut(Element<&mut N, &mut E>) -> bool,
400
    {
401
0
        FilterElements {
402
0
            iter: self,
403
0
            node_index: 0,
404
0
            map: Vec::new(),
405
0
            f,
406
0
        }
407
0
    }
408
}
409
410
impl<N, E, I: ?Sized> ElementIterator<N, E> for I where I: Iterator<Item = Element<N, E>> {}
411
412
/// An iterator that filters graph elements.
413
///
414
/// See [`.filter_elements()`][1] for more information.
415
///
416
/// [1]: trait.ElementIterator.html#method.filter_elements
417
#[derive(Debug, Clone)]
418
pub struct FilterElements<I, F> {
419
    iter: I,
420
    node_index: usize,
421
    map: Vec<usize>,
422
    f: F,
423
}
424
425
impl<I, F, N, E> Iterator for FilterElements<I, F>
426
where
427
    I: Iterator<Item = Element<N, E>>,
428
    F: FnMut(Element<&mut N, &mut E>) -> bool,
429
{
430
    type Item = Element<N, E>;
431
432
0
    fn next(&mut self) -> Option<Self::Item> {
433
        loop {
434
0
            let mut elt = self.iter.next()?;
435
0
            let keep = (self.f)(match elt {
436
0
                Element::Node { ref mut weight } => Element::Node { weight },
437
                Element::Edge {
438
0
                    source,
439
0
                    target,
440
0
                    ref mut weight,
441
0
                } => Element::Edge {
442
0
                    source,
443
0
                    target,
444
0
                    weight,
445
0
                },
446
            });
447
0
            let is_node = matches!(elt, Element::Node { .. });
448
0
            if !keep && is_node {
449
0
                self.map.push(self.node_index);
450
0
            }
451
0
            if is_node {
452
0
                self.node_index += 1;
453
0
            }
454
0
            if !keep {
455
0
                continue;
456
0
            }
457
458
            // map edge parts
459
0
            match elt {
460
                Element::Edge {
461
0
                    ref mut source,
462
0
                    ref mut target,
463
                    ..
464
                } => {
465
                    // Find the node indices in the map of removed ones.
466
                    // If a node was removed, the edge is as well.
467
                    // Otherwise the counts are adjusted by the number of nodes
468
                    // removed.
469
                    // Example: map: [1, 3, 4, 6]
470
                    // binary search for 2, result is Err(1). One node has been
471
                    // removed before 2.
472
0
                    match self.map.binary_search(source) {
473
0
                        Ok(_) => continue,
474
0
                        Err(i) => *source -= i,
475
                    }
476
0
                    match self.map.binary_search(target) {
477
0
                        Ok(_) => continue,
478
0
                        Err(i) => *target -= i,
479
                    }
480
                }
481
0
                Element::Node { .. } => {}
482
            }
483
0
            return Some(elt);
484
        }
485
0
    }
486
0
    fn size_hint(&self) -> (usize, Option<usize>) {
487
0
        let (_, upper) = self.iter.size_hint();
488
0
        (0, upper)
489
0
    }
490
}