• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vigna / webgraph-rs / 18573498435

16 Oct 2025 08:11PM UTC coverage: 48.064% (+0.04%) from 48.029%
18573498435

push

github

vigna
Docs consistency fix; minimal README.md for CLI and algo

8 of 12 new or added lines in 3 files covered. (66.67%)

433 existing lines in 14 files now uncovered.

3972 of 8264 relevant lines covered (48.06%)

22128303.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

70.73
/webgraph/src/graphs/vec_graph.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
 *
5
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6
 */
7

8
use crate::prelude::*;
9
use epserde::Epserde;
10
use lender::prelude::*;
11

12
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13
#[derive(Epserde, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
14
#[epserde_deep_copy]
15
pub struct LabeledArc<L>(usize, L);
16

17
impl<L> From<(usize, L)> for LabeledArc<L> {
18
    fn from((v, l): (usize, L)) -> Self {
1,432,877✔
19
        Self(v, l)
1,432,877✔
20
    }
21
}
22

23
impl<L> From<LabeledArc<L>> for (usize, L) {
24
    fn from(value: LabeledArc<L>) -> (usize, L) {
116✔
25
        (value.0, value.1)
116✔
26
    }
27
}
28

29
/// A mutable [`LabeledRandomAccessGraph`] implementation based on a vector of
30
/// vectors.
31
///
32
/// This implementation is faster and uses less resources than a
33
/// [`LabeledBTreeGraph`](crate::graphs::btree_graph::LabeledBTreeGraph), but it
34
/// is less flexible as arcs can be added only in increasing successor order.
35
///
36
/// This struct can be serialized with
37
/// [ε-serde](https://crates.io/crates/epserde). By setting the feature `serde`,
38
/// this struct can be serialized using [serde](https://crates.io/crates/serde),
39
/// too.
40
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41
#[derive(Epserde, Clone, Debug, PartialEq, Eq)]
42
pub struct LabeledVecGraph<L: Clone + 'static> {
43
    /// The number of arcs in the graph.
44
    num_arcs: u64,
45
    /// For each node, its list of successors.
46
    succ: Vec<Vec<LabeledArc<L>>>,
47
}
48

49
impl<L: Clone + 'static> core::default::Default for LabeledVecGraph<L> {
50
    fn default() -> Self {
×
UNCOV
51
        Self::new()
×
52
    }
53
}
54

55
impl<L: Clone + 'static> LabeledVecGraph<L> {
56
    /// Creates a new empty graph.
57
    pub fn new() -> Self {
1,034✔
58
        Self {
59
            num_arcs: 0,
60
            succ: vec![],
1,034✔
61
        }
62
    }
63

64
    /// Creates a new empty graph with `n` nodes.
UNCOV
65
    pub fn empty(n: usize) -> Self {
×
66
        Self {
67
            num_arcs: 0,
UNCOV
68
            succ: Vec::from_iter((0..n).map(|_| Vec::new())),
×
69
        }
70
    }
71

72
    /// Add an isolated node to the graph and return true if it is a new node.
73
    pub fn add_node(&mut self, node: usize) -> bool {
1,427,245✔
74
        let len = self.succ.len();
4,281,735✔
75
        self.succ.extend((len..=node).map(|_| Vec::new()));
5,753,445✔
76
        len <= node
1,427,245✔
77
    }
78

79
    /// Add an arc to the graph.
80
    ///
81
    /// New arcs must be added in increasing successor order, or this method
82
    /// will panic.
83
    ///
84
    /// # Panics
85
    ///
86
    /// This method will panic:
87
    /// - if one of the given nodes is greater or equal than the number of nodes
88
    ///   in the graph;
89
    /// - if the successor is lesser than or equal to the current last successor
90
    ///   of the source node.
91
    pub fn add_arc(&mut self, u: usize, v: usize, l: L) {
1,432,865✔
92
        let max = u.max(v);
5,731,460✔
93
        if max >= self.succ.len() {
2,865,730✔
94
            panic!(
×
95
                "Node {} does not exist (the graph has {} nodes)",
×
96
                max,
×
UNCOV
97
                self.succ.len(),
×
98
            );
99
        }
100
        let succ = &mut self.succ[u];
2,865,730✔
101

102
        match succ.last() {
1,432,865✔
103
            None => {
43,574✔
104
                succ.push((v, l).into());
43,574✔
105
                self.num_arcs += 1;
43,574✔
106
            }
107
            Some(LabeledArc(last, _label)) => {
2,778,582✔
108
                if v <= *last {
1,389,291✔
109
                    // arcs have to be inserted in increasing successor order
110
                    panic!(
×
UNCOV
111
                        "Error adding arc ({u}, {v}): successor is not increasing; the last arc inserted was ({u}, {last})"
×
112
                    );
113
                }
114
                succ.push((v, l).into());
5,557,164✔
115
                self.num_arcs += 1;
1,389,291✔
116
            }
117
        }
118
    }
119

120
    /// Add nodes and successors from an [`IntoLender`] yielding a
121
    /// [`NodeLabelsLender`].
122
    ///
123
    /// If the lender is sorted, consider using
124
    /// [`add_sorted_lender`](Self::add_sorted_lender), as it does not need to
125
    /// sort the output of the lender.
126
    pub fn add_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
194✔
127
    where
128
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
129
    {
130
        let mut arcs = Vec::new();
388✔
131
        for_!( (node, succ) in iter_nodes {
10,742✔
UNCOV
132
            self.add_node(node);
×
133
            for (v, l) in succ {
701,234✔
134
                arcs.push((v, l));
×
UNCOV
135
                self.add_node(v);
×
136
            }
UNCOV
137
            arcs.sort_by_key(|x| x.0);
×
138
            for (v, l) in arcs.drain(..) {
345,343✔
UNCOV
139
                self.add_arc(node, v, l);
×
140
            }
141
        });
142
        self
194✔
143
    }
144

145
    /// Creates a new graph from an [`IntoLender`] yielding a
146
    /// [`NodeLabelsLender`].
147
    ///
148
    /// If the lender is sorted, consider using
149
    /// [`from_sorted_lender`](Self::from_sorted_lender), as it does not need to
150
    /// sort the output of the lender.
151
    pub fn from_lender<I: IntoLender>(iter_nodes: I) -> Self
4✔
152
    where
153
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
154
    {
155
        let mut g = Self::new();
8✔
156
        g.add_lender(iter_nodes);
12✔
157
        g
4✔
158
    }
159

160
    /// Add nodes and successors from an [`IntoLender`] yielding a sorted
161
    /// [`NodeLabelsLender`].
162
    ///
163
    /// This method is faster than [`add_lender`](Self::add_lender) as
164
    /// it does not need to sort the output of the lender.
165
    pub fn add_sorted_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
2✔
166
    where
167
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
168
        I::Lender: SortedLender,
169
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator,
170
    {
171
        for_!( (node, succ) in iter_nodes {
22✔
UNCOV
172
            self.add_node(node);
×
173
            for (v, l) in succ {
68✔
174
                self.add_node(v);
×
UNCOV
175
                self.add_arc(node, v, l);
×
176
            }
177
        });
178
        self
2✔
179
    }
180

181
    /// Creates a new graph from a sorted [`IntoLender`] yielding a
182
    /// [`NodeLabelsLender`].
183
    ///
184
    /// This method is faster than [`from_lender`](Self::from_lender) as
185
    /// it does not need to sort the output of the lender.
186
    pub fn from_sorted_lender<I: IntoLender>(iter_nodes: I) -> Self
1✔
187
    where
188
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
189
        I::Lender: SortedLender,
190
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator,
191
    {
192
        let mut g = Self::new();
2✔
193
        g.add_sorted_lender(iter_nodes);
3✔
194
        g
1✔
195
    }
196

197
    /// Add nodes and successors from an [`IntoLender`] yielding a sorted
198
    /// [`NodeLabelsLender`] whose successors implement [`ExactSizeIterator`].
199
    ///
200
    /// This method has a better memory behavior than
201
    /// [`add_sorted_lender`](Self::add_sorted_lender) as it can allocate
202
    /// the right amount of memory for each node at once.
203
    pub fn add_exact_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
1✔
204
    where
205
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
206
        I::Lender: SortedLender,
207
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator + ExactSizeIterator,
208
    {
209
        for_!( (node, succ) in iter_nodes {
11✔
210
            self.add_node(node);
×
211
            let succ = succ.into_iter();
×
212
            let d = succ.len();
×
213
            self.succ[node].reserve_exact(d);
×
214
            self.succ[node].extend(succ.map(Into::into));
×
UNCOV
215
            self.num_arcs += d as u64;
×
216
        });
217
        self
1✔
218
    }
219

220
    /// Creates a new graph from a sorted [`IntoLender`] yielding a
221
    /// [`NodeLabelsLender`] whose successors implement [`ExactSizeIterator`].
222
    ///
223
    /// This method has a better memory behavior than
224
    /// [`from_sorted_lender`](Self::from_sorted_lender) as it can allocate
225
    /// the right amount of memory for each node at once.
226
    pub fn from_exact_lender<I: IntoLender>(iter_nodes: I) -> Self
1✔
227
    where
228
        I::Lender: for<'next> NodeLabelsLender<'next, Label = (usize, L)>,
229
        I::Lender: SortedLender,
230
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator + ExactSizeIterator,
231
    {
232
        let mut g = Self::new();
2✔
233
        g.add_exact_lender(iter_nodes);
3✔
234
        g
1✔
235
    }
236

237
    /// Add labeled arcs from an [`IntoIterator`], adding new nodes as needed.
238
    ///
239
    /// The items must be triples of the form `(usize, usize, l)` specifying an
240
    /// arc and its label.
241
    pub fn add_arcs(&mut self, arcs: impl IntoIterator<Item = (usize, usize, L)>) {
59✔
242
        let mut arcs = arcs.into_iter().collect::<Vec<_>>();
236✔
243
        arcs.sort_by_key(|x| (x.0, x.1));
1,710✔
244
        for (u, v, l) in arcs {
781✔
245
            self.add_node(u);
×
246
            self.add_node(v);
×
UNCOV
247
            self.add_arc(u, v, l);
×
248
        }
249
    }
250

251
    /// Creates a new graph from an [`IntoIterator`].
252
    ///
253
    /// The items must be triples of the form `(usize, usize, l)` specifying an
254
    /// arc and its label.
255
    pub fn from_arcs(arcs: impl IntoIterator<Item = (usize, usize, L)>) -> Self {
10✔
256
        let mut g = Self::new();
20✔
257
        g.add_arcs(arcs);
30✔
258
        g
10✔
259
    }
260

261
    /// Shrink the capacity of the graph to fit its current size.
262
    pub fn shrink_to_fit(&mut self) {
×
263
        self.succ.shrink_to_fit();
×
264
        for s in self.succ.iter_mut() {
×
UNCOV
265
            s.shrink_to_fit();
×
266
        }
267
    }
268
}
269

270
impl<L: Clone + 'static> SequentialLabeling for LabeledVecGraph<L> {
271
    type Label = (usize, L);
272
    type Lender<'a>
273
        = IteratorImpl<'a, Self>
274
    where
275
        Self: 'a;
276

277
    #[inline(always)]
278
    fn num_nodes(&self) -> usize {
64✔
279
        self.succ.len()
128✔
280
    }
281

282
    #[inline(always)]
283
    fn num_arcs_hint(&self) -> Option<u64> {
13✔
284
        Some(self.num_arcs())
13✔
285
    }
286

287
    #[inline(always)]
288
    fn iter_from(&self, from: usize) -> Self::Lender<'_> {
27✔
289
        IteratorImpl {
290
            labeling: self,
291
            nodes: (from..self.num_nodes()),
54✔
292
        }
293
    }
294
}
295

296
impl<'a, L: Clone + 'static> IntoLender for &'a LabeledVecGraph<L> {
297
    type Lender = <LabeledVecGraph<L> as SequentialLabeling>::Lender<'a>;
298

299
    #[inline(always)]
300
    fn into_lender(self) -> Self::Lender {
×
UNCOV
301
        self.iter()
×
302
    }
303
}
304

305
impl<L: Clone + 'static> LabeledSequentialGraph<L> for LabeledVecGraph<L> {}
306

307
impl<L: Clone + 'static> RandomAccessLabeling for LabeledVecGraph<L> {
308
    type Labels<'succ> = AssumeSortedIterator<
309
        core::iter::Map<
310
            core::iter::Cloned<core::slice::Iter<'succ, LabeledArc<L>>>,
311
            fn(LabeledArc<L>) -> (usize, L),
312
        >,
313
    >;
314
    #[inline(always)]
315
    fn num_arcs(&self) -> u64 {
22✔
316
        self.num_arcs
22✔
317
    }
318

319
    #[inline(always)]
320
    fn outdegree(&self, node: usize) -> usize {
193✔
321
        self.succ[node].len()
386✔
322
    }
323

324
    #[inline(always)]
325
    fn labels(&self, node: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
99✔
326
        unsafe { AssumeSortedIterator::new(self.succ[node].iter().cloned().map(Into::into)) }
495✔
327
    }
328
}
329

330
impl<L: Clone + 'static> LabeledRandomAccessGraph<L> for LabeledVecGraph<L> {}
331

332
impl<L: Clone + Sync> SplitLabeling for LabeledVecGraph<L> {
333
    type SplitLender<'a>
334
        = split::ra::Lender<'a, LabeledVecGraph<L>>
335
    where
336
        Self: 'a;
337

338
    type IntoIterator<'a>
339
        = split::ra::IntoIterator<'a, LabeledVecGraph<L>>
340
    where
341
        Self: 'a;
342

343
    fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
×
UNCOV
344
        split::ra::Iter::new(self, how_many)
×
345
    }
346
}
347

348
/// A mutable [`RandomAccessGraph`] implementation based on a vector of
349
/// vectors.
350
///
351
/// This implementation is faster and uses less resources than a [`BTreeGraph`],
352
/// but it is less flexible as arcs can be added only in increasing successor
353
/// order.
354
///
355
/// This struct can be serialized with
356
/// [ε-serde](https://crates.io/crates/epserde). By setting the feature `serde`,
357
/// this struct can be serialized using [serde](https://crates.io/crates/serde),
358
/// too.
359
///
360
/// # Implementation Notes
361
///
362
/// This is just a newtype for a [`LabeledVecGraph`] with
363
/// [`()`](https://doc.rust-lang.org/std/primitive.unit.html) labels. All
364
/// mutation methods are delegated.
365
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
366
#[derive(Epserde, Clone, Debug, Default, PartialEq, Eq)]
367
pub struct VecGraph(LabeledVecGraph<()>);
368

369
impl VecGraph {
370
    /// Creates a new empty graph.
371
    pub fn new() -> Self {
1,017✔
372
        LabeledVecGraph::new().into()
2,034✔
373
    }
374

375
    /// Creates a new empty graph with `n` nodes.
376
    pub fn empty(n: usize) -> Self {
×
UNCOV
377
        LabeledVecGraph::empty(n).into()
×
378
    }
379

380
    /// Add an isolated node to the graph and return true if it is a new node.
381
    pub fn add_node(&mut self, node: usize) -> bool {
1,288✔
382
        self.0.add_node(node)
3,864✔
383
    }
384

385
    /// Add an arc to the graph.
386
    ///
387
    /// New arcs must be added in increasing successor order, or this method
388
    /// will panic.
389
    ///
390
    /// # Panics
391
    ///
392
    /// This method will panic:
393
    /// - if one of the given nodes is greater or equal than the number of nodes
394
    ///   in the graph;
395
    /// - if the successor is lesser than or equal to the current last successor
396
    ///   of the source node.
397
    pub fn add_arc(&mut self, u: usize, v: usize) {
50,300✔
398
        self.0.add_arc(u, v, ())
251,500✔
399
    }
400

401
    /// Add nodes and successors from an [`IntoLender`] yielding a
402
    /// [`NodeLabelsLender`].
403
    ///
404
    /// If the lender is sorted, consider using
405
    /// [`add_sorted_lender`](Self::add_sorted_lender), as it does not need to
406
    /// sort the output of the lender.
407
    pub fn add_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
190✔
408
    where
409
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
410
    {
411
        self.0.add_lender(UnitLender(iter_nodes.into_lender()));
570✔
412
        self
190✔
413
    }
414

415
    /// Creates a new graph from an [`IntoLender`] yielding a
416
    /// [`NodeLabelsLender`].
417
    ///
418
    /// If the lender is sorted, consider using
419
    /// [`from_sorted_lender`](Self::from_sorted_lender), as it does not need to
420
    /// sort the output of the lender.
421
    pub fn from_lender<I: IntoLender>(iter_nodes: I) -> Self
190✔
422
    where
423
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
424
    {
425
        let mut g = Self::new();
380✔
426
        g.add_lender(iter_nodes);
570✔
427
        g
190✔
428
    }
429

430
    /// Add nodes and successors from an [`IntoLender`] yielding a sorted
431
    /// [`NodeLabelsLender`].
432
    ///
433
    /// This method is faster than [`add_lender`](Self::add_lender) as
434
    /// it does not need to sort the output of the lender.
435
    pub fn add_sorted_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
1✔
436
    where
437
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
438
        I::Lender: SortedLender,
439
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator,
440
    {
441
        self.0
1✔
442
            .add_sorted_lender(UnitLender(iter_nodes.into_lender()));
2✔
443
        self
1✔
444
    }
445

446
    /// Creates a new graph from a sorted [`IntoLender`] yielding a
447
    /// [`NodeLabelsLender`].
448
    ///
449
    /// This method is faster than [`from_lender`](Self::from_lender) as
450
    /// it does not need to sort the output of the lender.
451
    pub fn from_sorted_lender<I: IntoLender>(iter_nodes: I) -> Self
1✔
452
    where
453
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
454
        I::Lender: SortedLender,
455
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator,
456
    {
457
        let mut g = Self::new();
2✔
458
        g.add_sorted_lender(iter_nodes);
3✔
459
        g
1✔
460
    }
461

462
    /// Add nodes and successors from an [`IntoLender`] yielding a sorted
463
    /// [`NodeLabelsLender`] whose successors implement [`ExactSizeIterator`].
464
    ///
465
    /// This method has a better memory behavior than
466
    /// [`add_sorted_lender`](Self::add_sorted_lender) as it can allocate
467
    /// the right amount of memory for each node at once.
468
    pub fn add_exact_lender<I: IntoLender>(&mut self, iter_nodes: I) -> &mut Self
1✔
469
    where
470
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
471
        I::Lender: SortedLender,
472
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator + ExactSizeIterator,
473
    {
474
        for_!( (node, succ) in iter_nodes {
11✔
475
            self.add_node(node);
×
476
            let succ = succ.into_iter();
×
477
            let d = succ.len();
×
UNCOV
478
            self.0.succ[node].reserve_exact(d);
×
479
            self.0.succ[node].extend(succ.map(|x| LabeledArc(x, ())));
24✔
UNCOV
480
            self.0.num_arcs += d as u64;
×
481
        });
482
        self
1✔
483
    }
484

485
    /// Creates a new graph from a sorted [`IntoLender`] yielding a
486
    /// [`NodeLabelsLender`] whose successors implement [`ExactSizeIterator`].
487
    ///
488
    /// This method has a better memory behavior than
489
    /// [`from_sorted_lender`](Self::from_sorted_lender) as it can allocate
490
    /// the right amount of memory for each node at once.
491
    pub fn from_exact_lender<I: IntoLender>(iter_nodes: I) -> Self
1✔
492
    where
493
        I::Lender: for<'next> NodeLabelsLender<'next, Label = usize>,
494
        I::Lender: SortedLender,
495
        for<'succ> LenderIntoIter<'succ, I::Lender>: SortedIterator + ExactSizeIterator,
496
    {
497
        let mut g = Self::new();
2✔
498
        g.add_exact_lender(iter_nodes);
3✔
499
        g
1✔
500
    }
501

502
    /// Add arcs from an [`IntoIterator`], adding new nodes as needed.
503
    ///
504
    /// The items must be pairs of the form `(usize, usize)` specifying an arc.
505
    pub fn add_arcs(&mut self, arcs: impl IntoIterator<Item = (usize, usize)>) {
49✔
506
        self.0.add_arcs(arcs.into_iter().map(|(u, v)| (u, v, ())));
1,193✔
507
    }
508

509
    /// Creates a new graph from an [`IntoIterator`].
510
    ///
511
    /// The items must be pairs of the form `(usize, usize)` specifying an arc.
512
    pub fn from_arcs(arcs: impl IntoIterator<Item = (usize, usize)>) -> Self {
49✔
513
        let mut g = Self::new();
98✔
514
        g.add_arcs(arcs);
147✔
515
        g
49✔
516
    }
517

518
    /// Shrink the capacity of the graph to fit its current size.
519
    pub fn shrink_to_fit(&mut self) {
×
UNCOV
520
        self.0.shrink_to_fit();
×
521
    }
522
}
523

524
impl<'a> IntoLender for &'a VecGraph {
525
    type Lender = <VecGraph as SequentialLabeling>::Lender<'a>;
526

527
    #[inline(always)]
528
    fn into_lender(self) -> Self::Lender {
×
UNCOV
529
        self.iter()
×
530
    }
531
}
532

533
impl SequentialLabeling for VecGraph {
534
    type Label = usize;
535
    type Lender<'a>
536
        = IteratorImpl<'a, Self>
537
    where
538
        Self: 'a;
539

540
    #[inline(always)]
541
    fn num_nodes(&self) -> usize {
186✔
542
        self.0.num_nodes()
372✔
543
    }
544

545
    #[inline(always)]
546
    fn num_arcs_hint(&self) -> Option<u64> {
13✔
547
        self.0.num_arcs_hint()
26✔
548
    }
549

550
    #[inline(always)]
551
    fn iter_from(&self, from: usize) -> Self::Lender<'_> {
139✔
552
        IteratorImpl {
553
            labeling: self,
554
            nodes: (from..self.num_nodes()),
278✔
555
        }
556
    }
557
}
558

559
impl SequentialGraph for VecGraph {}
560

561
impl RandomAccessLabeling for VecGraph {
562
    type Labels<'succ> = AssumeSortedIterator<
563
        core::iter::Map<
564
            core::iter::Copied<core::slice::Iter<'succ, LabeledArc<()>>>,
565
            fn(LabeledArc<()>) -> usize,
566
        >,
567
    >;
568
    #[inline(always)]
569
    fn num_arcs(&self) -> u64 {
9✔
570
        self.0.num_arcs()
18✔
571
    }
572

573
    #[inline(always)]
574
    fn outdegree(&self, node: usize) -> usize {
193✔
575
        self.0.outdegree(node)
579✔
576
    }
577

578
    #[inline(always)]
579
    fn labels(&self, node: usize) -> <Self as RandomAccessLabeling>::Labels<'_> {
5,529✔
580
        // this is safe as we maintain each vector of successors sorted
581
        unsafe {
582
            AssumeSortedIterator::new(self.0.succ[node].iter().copied().map(|LabeledArc(x, _)| x))
22,116✔
583
        }
584
    }
585
}
586

587
impl RandomAccessGraph for VecGraph {}
588

589
impl From<LabeledVecGraph<()>> for VecGraph {
590
    fn from(g: LabeledVecGraph<()>) -> Self {
1,017✔
591
        VecGraph(g)
1,017✔
592
    }
593
}
594

595
impl SplitLabeling for VecGraph {
596
    type SplitLender<'a>
597
        = split::ra::Lender<'a, VecGraph>
598
    where
599
        Self: 'a;
600

601
    type IntoIterator<'a>
602
        = split::ra::IntoIterator<'a, VecGraph>
603
    where
604
        Self: 'a;
605

606
    fn split_iter(&self, how_many: usize) -> Self::IntoIterator<'_> {
×
UNCOV
607
        split::ra::Iter::new(self, how_many)
×
608
    }
609
}
610

611
#[cfg(test)]
612
mod test {
613
    use super::*;
614
    #[test]
615
    fn test_vec_graph() {
616
        let mut arcs = vec![
617
            (0, 1, Some(1.0)),
618
            (0, 2, None),
619
            (1, 2, Some(2.0)),
620
            (2, 4, Some(f64::INFINITY)),
621
            (3, 4, Some(f64::NEG_INFINITY)),
622
            (1, 3, Some(f64::NAN)),
623
        ];
624
        let g = LabeledVecGraph::<_>::from_arcs(arcs.iter().copied());
625
        assert_ne!(
626
            g, g,
627
            "The label contains a NaN which is not equal to itself so the graph must be not equal to itself"
628
        );
629

630
        arcs.pop();
631
        let g = LabeledVecGraph::<_>::from_arcs(arcs);
632
        assert_eq!(g, g, "Without NaN the graph should be equal to itself");
633
    }
634
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc