Skip to content

Commit efb5063

Browse files
committed
Add best_backup_generic helper in path_selection
1 parent 2d279a2 commit efb5063

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

src/bgp/path_selection.rs

+64
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,70 @@ pub fn best_backup<'a, OS, T>(
607607
(best, backup)
608608
}
609609

610+
/// Alternative, generic version of `fn best_backup`.
611+
///
612+
/// This method takes any iterator providing Items implementing Ord, such as
613+
/// `OrdRoute`. As such, it has little to do with routes or path selection per
614+
/// se.
615+
///
616+
/// Note that because of this genericness, we have no access to methods or
617+
/// members of `T`, and thus are unable to compare actual contents such as a
618+
/// `PaMap` or the `TiebreakerInfo`. This means the method can not check for
619+
/// any duplicate route information between `T`s, and really only order them.
620+
/// The caller therefore has to make sure to pass in an iterator that does not
621+
/// yield any duplicate routes.
622+
///
623+
/// This method enables the caller to attach additional information, as long
624+
/// as it implements `Ord`. For example, one can pass in an iterator over
625+
/// tuples of `OrdRoute` and something else. As long as the `OrdRoute` is the
626+
/// first member of that tuple and no duplicates are yielded from the
627+
/// iterator, the additional information is not used in the ordering process
628+
/// but is returned together with the 'best' and 'backup' tuples. This can be
629+
/// useful when the caller needs to relate routes to local IDs or something
630+
/// alike.
631+
///
632+
pub fn best_backup_generic<I, T>(it: I) -> (Option<T>, Option<T>)
633+
where
634+
I: Iterator<Item = T>,
635+
T: Ord
636+
{
637+
let mut best = None;
638+
let mut backup = None;
639+
640+
for c in it {
641+
match best.take() {
642+
None => { best = Some(c); continue }
643+
Some(cur_best) => {
644+
if c < cur_best {
645+
// c is preferred over current best
646+
best = Some(c);
647+
backup = Some(cur_best);
648+
continue;
649+
}
650+
// put it back in
651+
best = Some(cur_best);
652+
653+
// c is not better than best, now check backup
654+
match backup.take() {
655+
None => { backup = Some(c); }
656+
Some(cur_backup) => {
657+
if c < cur_backup {
658+
// c is preferred over current backup
659+
backup = Some(c);
660+
} else {
661+
// put it back in
662+
backup = Some(cur_backup);
663+
}
664+
665+
}
666+
}
667+
}
668+
}
669+
}
670+
671+
(best, backup)
672+
}
673+
610674
/*
611675
pub fn best_multistrat<'a, OS1: 'a + OrdStrat, OS2: 'a + OrdStrat, I>(it: I)
612676
-> Option<(OrdRoute<'a, OS1>, OrdRoute<'a, OS2>)>

0 commit comments

Comments
 (0)