FallbackState: Use itertools::merge_join_by.
This replaces a hand-coded replacement that was probably a little less efficient.
This commit is contained in:
parent
b752c6c771
commit
9803b645c0
|
@ -151,86 +151,19 @@ impl FallbackState {
|
||||||
|
|
||||||
/// Consume `other` and copy all of its fallback status entries into the corresponding entries for `self`.
|
/// Consume `other` and copy all of its fallback status entries into the corresponding entries for `self`.
|
||||||
pub(crate) fn take_status_from(&mut self, other: FallbackState) {
|
pub(crate) fn take_status_from(&mut self, other: FallbackState) {
|
||||||
matching_items(
|
use itertools::EitherOrBoth::Both;
|
||||||
|
|
||||||
|
itertools::merge_join_by(
|
||||||
self.fallbacks.iter_mut(),
|
self.fallbacks.iter_mut(),
|
||||||
other.fallbacks.into_iter(),
|
other.fallbacks.into_iter(),
|
||||||
|a, b| a.fallback.id().cmp(b.fallback.id()),
|
|a, b| a.fallback.id().cmp(b.fallback.id()),
|
||||||
)
|
)
|
||||||
.for_each(|(entry, other)| {
|
.for_each(|entry| {
|
||||||
debug_assert_eq!(entry.fallback.id(), other.fallback.id());
|
if let Both(entry, other) = entry {
|
||||||
entry.status = other.status;
|
debug_assert_eq!(entry.fallback.id(), other.fallback.id());
|
||||||
});
|
entry.status = other.status;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return an iterator that iterates over two sorted lists and yields all items
|
|
||||||
/// from those lists that match according to a comparison function.
|
|
||||||
///
|
|
||||||
/// Results may be incorrect if the input lists are not sorted, but the iterator
|
|
||||||
/// should not panic.
|
|
||||||
///
|
|
||||||
/// TODO: If this proves generally useful, move it to another tor-basic-utils or
|
|
||||||
/// a new crate. If there is already functionality for this externally, use it.
|
|
||||||
fn matching_items<I1, I2, F>(iter1: I1, iter2: I2, cmp: F) -> MatchingItems<I1, I2, F>
|
|
||||||
where
|
|
||||||
I1: Iterator,
|
|
||||||
I2: Iterator,
|
|
||||||
F: FnMut(&I1::Item, &I2::Item) -> std::cmp::Ordering,
|
|
||||||
{
|
|
||||||
MatchingItems {
|
|
||||||
iter1: iter1.peekable(),
|
|
||||||
iter2: iter2.peekable(),
|
|
||||||
cmp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type to implement `matching_items()`
|
|
||||||
struct MatchingItems<I1, I2, F>
|
|
||||||
where
|
|
||||||
I1: Iterator,
|
|
||||||
I2: Iterator,
|
|
||||||
F: FnMut(&I1::Item, &I2::Item) -> std::cmp::Ordering,
|
|
||||||
{
|
|
||||||
/// The first iterator to examine
|
|
||||||
iter1: std::iter::Peekable<I1>,
|
|
||||||
/// The second iterator to examine
|
|
||||||
iter2: std::iter::Peekable<I2>,
|
|
||||||
/// A function to compare the items in the two iterators.
|
|
||||||
cmp: F,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I1, I2, F> Iterator for MatchingItems<I1, I2, F>
|
|
||||||
where
|
|
||||||
I1: Iterator,
|
|
||||||
I2: Iterator,
|
|
||||||
F: FnMut(&I1::Item, &I2::Item) -> std::cmp::Ordering,
|
|
||||||
{
|
|
||||||
type Item = (I1::Item, I2::Item);
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
use std::cmp::Ordering::*;
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let (n1, n2) = match (self.iter1.peek(), self.iter2.peek()) {
|
|
||||||
(Some(a), Some(b)) => (a, b),
|
|
||||||
(_, _) => return None, // at least one iterator is exhausted.
|
|
||||||
};
|
|
||||||
|
|
||||||
match (self.cmp)(n1, n2) {
|
|
||||||
Less => {
|
|
||||||
let _ignore = self.iter1.next();
|
|
||||||
}
|
|
||||||
Equal => {
|
|
||||||
return Some((
|
|
||||||
self.iter1.next().expect("Peek/Next inconsistency"),
|
|
||||||
self.iter2.next().expect("Peek/Next inconsistency"),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Greater => {
|
|
||||||
let _ignore = self.iter2.next();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,31 +172,6 @@ mod test {
|
||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_matching_items() {
|
|
||||||
let odds = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19];
|
|
||||||
let primes = ["2", "3", "5", "7", "11", "13", "17", "19"];
|
|
||||||
|
|
||||||
let matches: Vec<_> = super::matching_items(odds.iter(), primes.iter(), |i, s| {
|
|
||||||
(*i).cmp(&s.parse().unwrap())
|
|
||||||
})
|
|
||||||
.map(|(i, s)| (*i, *s))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
matches,
|
|
||||||
vec![
|
|
||||||
(3, "3"),
|
|
||||||
(5, "5"),
|
|
||||||
(7, "7"),
|
|
||||||
(11, "11"),
|
|
||||||
(13, "13"),
|
|
||||||
(17, "17"),
|
|
||||||
(19, "19")
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Construct a `FallbackDir` with random identity keys and addresses.
|
/// Construct a `FallbackDir` with random identity keys and addresses.
|
||||||
///
|
///
|
||||||
/// Since there are 416 bits of random id here, the risk of collision is
|
/// Since there are 416 bits of random id here, the risk of collision is
|
||||||
|
|
Loading…
Reference in New Issue